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.
不幸的是,我不知道如何翻译该方法的where TA : TZ
类型约束Bind
。我认为它应该是类似′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!
}