linq f# seq

F#equivalente de LINQ Single



seq (2)

Ok, entonces para la mayoría de las operaciones LINQ hay un equivalente de F #. (Generalmente en el módulo Seq, desde Seq = IEnumerable)

No puedo encontrar el equivalente de IEmumerable.Single , prefiero Single over First (que es Seq.find), porque es más defensivo - afirma para mí que el estado es lo que espero.

Entonces veo un par de soluciones (además de usar Seq.find). (Estos podrían escribirse como métodos de extensión)

La firma de tipo para esta función, que estoy llamando solo, es

(''a->bool) -> seq<''a> -> ''a let only = fun predicate src -> System.Linq.Enumerable.Single<''a>(src, predicate) let only2 = Seq.filter >> Seq.exactlyOne

only2 es preferido, sin embargo no compilará (¿hay alguna pista sobre eso?).


Qué pasa

let Single source f = let worked = ref false let newf = fun a -> match f a with |true -> if !worked = true then failwith "not single" worked := true Some(a) |false -> None let r = source |> Seq.choose newf Seq.nth 0 r

Muy unidiomático pero probablemente cercano al óptimo

EDITAR:

Solución con exactlyOne

let only2 f s= (Seq.filter f s) |> exactlyOne


En F # 2.0, esta es una solución que funciona sin enumerar toda la secuencia (cerca de su segundo enfoque):

module Seq = let exactlyOne seq = match seq |> Seq.truncate 2 with | s when Seq.length s = 1 -> s |> Seq.head |> Some | _ -> None let single predicate = Seq.filter predicate >> exactlyOne

Elijo devolver el tipo de option ya que elevar la excepción es bastante inusual en las funciones de alto orden F #.

EDITAR:

En F # 3.0, como @Oxinabox se menciona en su comentario, Seq.exactlyOne existe en el módulo Seq.