2012-07-28 46 views
2

由於我需要花費很多時間來關注一下,所以我建立了一個一次性使用函數列表和一個傳遞函數來添加項目作爲一個側面效果:類型推理會產生不必要的約束

let mutable disposables = [] 
let (~-) (x:'a) = disposables <- x :: disposables; x 

所以,我希望能做到這一點:

let thing1 = -new Form() 
let thing2 = -new Control() 

for i in disposables do i.Dispose() 

的問題是,F#自動限制'aIDisposable,與報警信息:

此構造使得代碼不如類型註釋所指示的通用。類型變量'a被限制爲'IDisposable'類型。

那麼返回類型operator ~-就變成了IDisposable,這就損害了函數的方便性。

有沒有辦法阻止F#創建這個約束?

+0

如果「一次性」是「IDisposable」的列表,那麼'x'可以是「IDisposable」本身嗎?無論如何,你可能會給「一次性」一個明確的類型,看看你得到了什麼 - 我是一個Haskeller,所以這只是猜測。 – 2012-07-28 01:01:43

+0

做內聯(〜 - )(x:'a)=一次性< - x ::一次性; x'解決這個問題? – 2012-07-28 01:07:52

+0

@JohnPalmer Nope,'本地類綁定不能標記爲內聯。考慮將定義從類中提取出來,否則不要將其標記爲內聯。 – 2012-07-28 01:09:05

回答

2

Got it!

答案是上溯造型xIDisposable當我在函數中使用它,而不是在函數的類型簽名:

let mutable disposables = [] 
let (~-) x = disposables <- (x :> IDisposable) :: disposables; x 
+0

'(upcast x)'讀取比'(x:> IDisposable)'IMO好一點,但您需要給出'一次性'一個明確的類型。 – ildjarn 2012-07-28 01:56:28

1

你沒有問有關你的代碼一般建議,但我覺得有必要指出一些古怪。

首先,你應該幾乎不需要撥打Dispose()use是管理資源的標準方式。或許你也應該這樣做:

use thing1 = new Form() 
use thing2 = new Control() 

其次,爲什麼你會一個不變的數據結構分配給mutable變量?如果你確信你需要手動跟蹤資源使用

let disposables = ResizeArray<IDisposable>() 

最後,你應該覺得漫長而艱難界定變異範圍之外的變量的操作之前。這對於操作員來說是不尋常的行爲(除非操作員的範圍很窄)。

+0

儘管我想使用'use',我正在開發遊戲代碼,所以我不得不使用.NET Framework的本地習語來提高效率,尤其是爲了避免調用GC許多。我經常使用類,因爲每次調用時,閉包都會在堆上分配。就使用列表而言,我不介意太多的開銷,因爲一次性代碼大部分都是巨大的資源,我不會創建很多代碼 - 所以列表和ResizeArray之間沒有任何實際的區別。 – 2012-07-28 07:16:29