F # дает мне некоторые проблемы с его правилами вывода типа. Я пишу простой построитель вычислений, но не могу получить ограничения на общий тип переменных.Как преобразовать ограничение параметра типа `T: U` с C# на 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.
Unfortu Я не знаю, как бы я перевел ограничение типа 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!
}
Хорошо, теперь я уверен, что нет четкого решения для того, что я хотел бы сделать. Указание 'obj' для' finallyAction' имеет неприятный побочный эффект, уменьшающий все мои пользовательские привязанные значения ('let!') В пользовательском потоке операций, чтобы ввести 'obj', что означает, что я не могу действительно разумно работать с ними дольше. Нужно будет подумать о том, как реализовать этот строитель по-разному. Но я надеюсь, что они исправит это в будущей версии языка F # ... – stakx
@stakx: Даже если вы используете 'obj', тип значений, связанных с использованием' let! ', Должен быть фактическим (более конкретным) типом , Я отредактировал ответ, чтобы включить пример, демонстрирующий это (я, наконец, тоже тестировал это :-)). –
Ты волшебник! :) Я предполагаю, что все эти аннотации типа мешали. Благодаря! – stakx