F # дает мне некоторую проблему с его правилами вывода типов. Я пишу простой построитель вычислений, но не могу получить ограничения на основные переменные типа.
Код, который мне нужен, выглядит следующим образом: С#:
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!
}