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!
}