Ok, so for most LINQ operations there is a F# equivalent. (Generally in the Seq module, since Seq= IEnumerable)
I can\'t find the equiv of IEmumerable.Single
What about
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
Very unidiomatic but probably close to optimal
Solution with exactlyOne
let only2 f s= (Seq.filter f s) |> exactlyOne
In F# 2.0, this is a solution works without enumerating the whole sequence (close to your 2nd approach):
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
I choose to return option
type since raising exception is quite unusual in F# high-order functions.
EDIT:
In F# 3.0, as @Oxinabox mentioned in his comment, Seq.exactlyOne exists in Seq module.