4

わかりました。ほとんどの LINQ 操作には、F# に相当するものがあります。(Seq= IEnumerable であるため、通常は Seq モジュールにあります)

と同等のものを見つけることができません。(Seq.find である) よりも優先します。これはより防御的であるためです。状態が期待どおりであると主張しIEmumerable.SingleますSingleFirst

したがって、いくつかの解決策があります (Seq.find を使用する以外に)。(これらは拡張メソッドとして記述できます)

私だけが呼び出しているこの関数の型シグネチャは、

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

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

let only2 = Seq.filter >> Seq.exactlyOne

only2が推奨されますが、コンパイルされません (その手がかりはありますか?)。

4

2 に答える 2

3

F#2.0では、これはシーケンス全体を列挙せずに機能するソリューションです(2番目のアプローチに近い)。

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

optionF#の高階関数では例外を発生させることは非常にまれなので、型を返すことにしました。

編集:

F#3.0では、@ Oxinaboxがコメントで述べたように、Seq.exactlyOneはSeqモジュールに存在します。

于 2012-03-24T10:32:11.677 に答える
3

どうですか

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 

非常に一元的だが、おそらく最適に近い

編集:

ソリューションexactlyOne

let only2 f s= (Seq.filter f s) |> exactlyOne
于 2012-03-24T10:19:51.070 に答える