Как мне перевести параметр универсального типа `where T: U` ограничение с C # на F #?

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! 
}
16
задан stakx supports GoFundMonica 9 July 2014 в 07:28
поделиться