... o, ¿cómo puedo filtrar una secuencia de clases por las interfaces que implementan?F # Equivalente a Enumerable.OfType <'a>
Digamos que tengo una secuencia de objetos que heredan de Foo, un seq<#Foo>
. En otras palabras, mi secuencia contendrá una o más de cuatro subclases diferentes de Foo.
Cada subclase implementa una interfaz independiente diferente que no comparte nada con las interfaces implementadas por las otras subclases.
Ahora necesito filtrar esta secuencia solo a los elementos que implementan una interfaz en particular.
La versión C# es simple:
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);
}
}
}
podría utilizar LINQ de F #:
let mergeFoosIntoList (foos:seq<#Foo>) (dest:IList<'a>) =
System.Linq.Enumerable.OfType<'a>(foos)
|> Seq.iter dest.Add
Sin embargo, creo que debe haber una manera más idiomática para lograrlo. Pensé que esto iba a funcionar ...
let mergeFoosIntoList (foos:seq<#Foo>) (dest:IList<'a>) =
foos
|> Seq.choose (function | :? 'a as x -> Some(x) | _ -> None)
|> Seq.iter dest.Add
Sin embargo, el compilador se queja de :? 'a
- me dice:
Esta coerción tiempo de ejecución o el tipo de prueba de tipo 'b a' A implica un tipo indeterminado basado en la información anterior a este punto del programa. Las pruebas de tipo de tiempo de ejecución no están permitidas en algunos tipos. Se necesitan anotaciones de tipo adicionales.
No puedo averiguar qué tipo adicional de anotaciones agregar. No existe relación entre la interfaz 'a
y #Foo
, excepto que una o más subclases de Foo implementan esa interfaz. Además, no existe relación entre las diferentes interfaces que se pueden pasar como 'a
, excepto que todas ellas están implementadas por subclases de Foo.
Espero impacientemente golpearme en la cabeza tan pronto como una de ustedes, amable, señale lo obvio que me he perdido.
Que hizo el truco. ¡Gracias! –
@Brian - ¿pero seguirías esta ruta? En este caso, OfType parece mucho más bonito ... – Benjol
Si solo se trata de sintaxis y no de rendimiento, sería bastante fácil extender el módulo Seq con una función 'ofType <'a>'. Entonces el cuerpo del método sería: 'pets |> Seq.ofType <'a> |> Seq.iter dest.Add' –