Sto provando a chiamare un metodo .NET che accetta un generico IEnumerable<T>
da F # utilizzando un seq<U>
tale che U sia una sottoclasse di T. Questo non funziona come mi aspettavo sarebbe:F # e covarianza di interfaccia: cosa fare? (in particolare seq <> alias IEnumerable <>)
Con la seguente semplice stampante:
let printEm (os: seq<obj>) =
for o in os do
o.ToString() |> printfn "%s"
Questi sono i risultati che ottengo:
Seq.singleton "Hello World" |> printEm // error FS0001;
//Expected seq<string> -> 'a but given seq<string> -> unit
Seq.singleton "Hello World" :> seq<obj> |> printEm // error FS0193;
//seq<string> incompatible with seq<obj>
Seq.singleton "Hello World" :?> seq<obj> |> printEm // works!
Seq.singleton 42 :> seq<obj> |> printEm // error FS0193
Seq.singleton 42 :?> seq<obj> |> printEm // runtime InvalidCastException!
//Unable to cast object of type '[email protected][System.Int32]'
// to type 'System.Collections.Generic.IEnumerable`1[System.Object]'.
Idealmente, mi piacerebbe la prima sintassi per lavorare - o qualcosa di più vicino al è come po ssible, con controllo del tipo di tempo compilato. Non capisco dove il compilatore trovi una funzione seq<string> -> unit
in quella linea, ma apparentemente covarianza per IEnumerable non funziona e che in qualche modo si traduce in quel messaggio di errore. L'utilizzo di un cast esplicito genera un messaggio di errore ragionevole, ma non funziona neanche. L'uso di un cast runtime funziona, ma solo per le stringhe, gli ints falliscono con un'eccezione (sgradevole).
Sto cercando di interoperare con altri codici .NET; è per questo che ho bisogno di tipi specifici IEnumerable.
Qual è il modo più pulito e preferibilmente efficiente per il casting di interfacce co o controvarianti come IEnumerable in F #?
Come dice desco, la soluzione più pulita è quella di modificare (o rimuovere) la dichiarazione del tipo su 'os' (se possibile). Su una nota non correlata, 'o.ToString |> printfn"% s "' può essere scritto in modo più conciso come 'o |> printfn"% O "'. – kvb
@kvb Penso che @Eamon non abbia problemi con la funzione 'printfn'. –