F#給我的類型推理規則帶來一些麻煩。我正在編寫一個簡單的計算生成器,但無法正確獲取我的泛型類型變量約束。如何將`where T:U`通用類型參數約束從C#轉換爲F#?
,我想代碼看起來在C#如下:
class FinallyBuilder<TZ>
{
readonly Action<TZ> finallyAction;
public FinallyBuilder(Action<TZ> finallyAction)
{
this.finallyAction = finallyAction;
}
public TB Bind<TA, TB>(TA x, Func<TA, TB> cont) where TA : TZ
{ // ^^^^^^^^^^^^^
try // this is what gives me a headache
{ // in the F# version
return cont(x);
}
finally
{
finallyAction(x);
}
}
}
最好的(但非編譯代碼)我已經拿出了F#版本到目前爲止是:
type FinallyBuilder<′z> (finallyAction : ′z -> unit) =
member this.Bind (x : ′a) (cont : ′a -> ′b) =
try cont x
finally finallyAction (x :> ′z) // cast illegal due to missing constraint
// Note: ' changed to ′ to avoid bad syntax highlighting here on SO.
Unfortu最近,我不知道如何翻譯Bind
方法的where TA : TZ
類型約束。我認爲它應該是類似於′a when ′a :> ′z
,但F#編譯器不喜歡這個地方,我總是最終得到一些泛型類型變量約束到另一個。
難道有人請讓我看看正確的F#代碼嗎?
背景:我的目標是能寫的F#的定製工作流程是這樣的:
let cleanup = new FinallyBuilder (fun x -> ...)
cleanup {
let! x = ... // x and y will be passed to the above lambda function at
let! y = ... // the end of this block; x and y can have different types!
}
好吧,我現在相當確信沒有完美的解決方案,我想要做什麼。爲'finallyAction'指定'obj'具有令人討厭的副作用,即將自定義工作流中的所有自定義綁定('let!')值都減少爲鍵入'obj',這意味着我無法真正與他們合作更長的時間。需要更多地考慮如何以不同的方式實現該構建器。但是我希望他們能夠在未來版本的F#語言中解決這個問題...... – stakx 2010-11-13 16:55:25
@stakx:即使你使用'obj',使用'let!'綁定的值的類型應該是實際的(更具體的)類型。我編輯的答案包括一個例子,說明了這一點(我最終也測試了它:-))。 – 2010-11-13 17:27:12
你是一個巫師! :)那麼,我猜所有這些類型的註釋都是如此。謝謝! – stakx 2010-11-13 17:34:53