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.
К сожалению, я не знаю, как бы я перевел ограничение типа где 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!
}