F# equivalent of LINQ Single

偶尔善良 提交于 2019-11-28 09:39:51

问题


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, I prefer Single over First (which is Seq.find), because it is more defensive - it asserts for me the state is what I expect.

So I see a couple of solutions (other than than using Seq.find). (These could be written as extension methods)

The type signature for this function, which I'm calling only, is

('a->bool) -> seq<'a> -> 'a

let only =  fun predicate src -> System.Linq.Enumerable.Single<'a>(src, predicate)

let only2 = Seq.filter >> Seq.exactlyOne

only2 is preferred, however it won't compile (any clues on that?).


回答1:


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.




回答2:


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

EDIT:

Solution with exactlyOne

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


来源:https://stackoverflow.com/questions/9850769/f-equivalent-of-linq-single

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!