F # me está dando algunos problemas con sus reglas de inferencia tipo. Estoy escribiendo un simple generador de cálculos pero no puedo obtener mis restricciones de tipo genérico correctas.¿Cómo puedo traducir una restricción de parámetro de tipo genérico `where T: U` de C# a F #?
El código que me gustaría que se ve de la siguiente manera en 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);
}
}
}
La mejor (pero no compilar código) me ha ocurrido con el F # la versión hasta ahora es:
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 Nately, no tengo ni idea de cómo traduciría la restricción de tipo where TA : TZ
en el método Bind
. Pensé que debería ser algo así como ′a when ′a :> ′z
, pero al compilador de F # no le gusta esto en cualquier lugar y siempre termino con una variable de tipo genérico restringida a otra.
¿Podría alguien mostrarme el código F # correcto?
Antecedentes: Mi objetivo es ser capaz de escribir un flujo de trabajo # encargo F así:
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!
}
OK, estoy bastante convencido de que no hay una solución clara para lo que me gustaría hacer. Especificar 'obj' para' finallyAction' tiene el desagradable efecto secundario de reducir todos mis valores de límite personalizado ('let!') En el flujo de trabajo personalizado para escribir 'obj', lo que significa que no puedo hacer un trabajo sensato con ellos. más. Tendrá que pensar un poco más sobre cómo implementar ese generador de forma diferente. Pero espero que lo solucionen en una versión futura del lenguaje F # ... – stakx
@stakx: incluso si usa 'obj', el tipo de valores vinculados con' let! 'Debería ser el tipo real (más específico) . Edité la respuesta para incluir un ejemplo que demuestre esto (finalmente lo probé también :-)). –
¡eres un mago! :) Supongo que todas esas anotaciones tipo se interpusieron en el camino, entonces. ¡Gracias! – stakx