F # mi sta dando qualche problema con le sue regole di inferenza di tipo. Sto scrivendo un semplice costruttore di calcoli ma non riesco a ottenere il mio tipo generico di vincoli di variabile.Come si traduce un vincolo di parametro generico `dove T: U` da C# a F #?
Il codice che vorrei si rappresenta come segue 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 migliore (ma non la compilazione di codice) mi è venuta in mente per il F # versione finora è:
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, non ho idea di come tradurrei il vincolo di tipo where TA : TZ
nel metodo Bind
. Ho pensato che dovrebbe essere qualcosa come ′a when ′a :> ′z
, ma il compilatore F # non mi piace da nessuna parte e finisco sempre con qualche variabile di tipo generico vincolata a un'altra.
Qualcuno potrebbe mostrarmi il codice F # corretto?
Background: Il mio obiettivo è quello di essere in grado di scrivere un F flusso di lavoro # personalizzato come questo:
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, sono abbastanza convinto ora che non esiste una soluzione chiara per quello che mi piacerebbe fare. Specificare 'obj' per' finallyAction' ha il brutto effetto collaterale di ridurre tutti i miei valori personalizzati ('let!') Nel flusso di lavoro personalizzato per digitare 'obj', il che significa che non posso davvero fare un buon lavoro con loro più a lungo. Dovrà pensare ancora un po 'su come implementare quel costruttore in modo diverso. Ma spero che risolveranno tutto ciò in una versione futura del linguaggio F # ... – stakx
@stakx: Anche se usi 'obj', il tipo di valori associati usando' let! 'Dovrebbe essere il tipo effettivo (più specifico) . Ho modificato la risposta includendo un esempio che dimostra ciò (l'ho finalmente testato anche io :-)). –
sei un mago! :) Immagino che tutte quelle annotazioni di tipo siano d'intralcio, quindi. Grazie! – stakx