... o, come si filtra una sequenza di classi dalle interfacce che implementano?F # Equivalente a Enumerable.OfType <'a>
Diciamo che ho una sequenza di oggetti che ereditano da Foo, uno seq<#Foo>
. In altre parole, la mia sequenza conterrà una o più di quattro diverse sottoclassi di Foo.
Ciascuna sottoclasse implementa un'interfaccia indipendente diversa che non condivide nulla con le interfacce implementate dalle altre sottoclassi.
Ora ho bisogno di filtrare questa sequenza solo per gli elementi che implementano una particolare interfaccia.
Il C# versione è semplice:
void MergeFoosIntoList<T>(IEnumerable<Foo> allFoos, IList<T> dest)
where T : class
{
foreach (var foo in allFoos)
{
var castFoo = foo as T;
if (castFoo != null)
{
dest.Add(castFoo);
}
}
}
potevo usare LINQ da F #:
let mergeFoosIntoList (foos:seq<#Foo>) (dest:IList<'a>) =
System.Linq.Enumerable.OfType<'a>(foos)
|> Seq.iter dest.Add
Tuttavia, mi sento come ci dovrebbe essere un modo più idiomatico per realizzarlo. Ho pensato che questo avrebbe funzionato ...
let mergeFoosIntoList (foos:seq<#Foo>) (dest:IList<'a>) =
foos
|> Seq.choose (function | :? 'a as x -> Some(x) | _ -> None)
|> Seq.iter dest.Add
Tuttavia, il compilatore lamenta :? 'a
- dicendomi:
Questa coercizione runtime o tipo di test dal tipo 'b per' un comporta un tipo indeterminata base sulle informazioni prima di questo punto del programma. I test del tipo runtime non sono consentiti su alcuni tipi. Sono necessarie ulteriori annotazioni sul tipo.
Non riesco a capire quali ulteriori annotazioni di tipo aggiungere. Non esiste alcuna relazione tra l'interfaccia 'a
e #Foo
eccetto che una o più sottoclassi di Foo implementano tale interfaccia. Inoltre, non esiste alcuna relazione tra le diverse interfacce che possono essere passate come 'a
eccetto che sono tutte implementate da sottoclassi di Foo.
Prevedo con impazienza di schiaffeggiarmi in testa non appena uno di voi gentili persone sottolinea la cosa ovvia che mi è mancata.
Che ha fatto il trucco. Grazie! –
@Brian - ma andresti su questa strada? In questo caso, OfType sembra molto più bello ... – Benjol
Se si tratta solo di sintassi e non di prestazioni, sarebbe abbastanza semplice estendere il modulo Seq con una funzione 'ofType <'a>'. Quindi il corpo del metodo sarebbe semplicemente: 'pets |> Seq.ofType <'a> |> Seq.iter dest.Add' –