2103


以下のようなリストがあった場合に、`Some`の要素のみを取り出す方法を教えてください。

[code]

    let xs = [ Some 10; None; Some 30; Some 2; None ]
    
[/code]

単に`filter`しただけだと、`Some`が残ってしまいますが、`Some`だけを取り出しているのでこれを取り除きたいです。

[code]

    let res =
      xs
      |> List.filter Option.isSome
      |> List.map Option.get // [ 10; 30; 2 ]
    
[/code]

これで一応実現はできますが、(`Option.isSome`でフィルタしているから大丈夫だとはいえ)`Option.get`を使っているのが危険な感じがして気持ち悪いです。


CC BY-SA 3.0
2014-12-19T05:17:25.807
2102
2014-12-19T05:54:12.573
2014-12-19T05:54:12.573
3313
4482
question
.net f#
optionのリストから、Someの要素のみを取り出す方法を教えてください


[`List.choose`関数](http://msdn.microsoft.com/ja-
jp/library/ee353456.aspx)を使いましょう。 これを使うと、以下のように書けます。

[code]

    let res = xs |> List.choose id
    
[/code]

`List.choose`は、`'a -> 'b
option`という関数を受け取り、`Some`が返されるとそれに包まれた値のみを結果に含むようなリストが返されます。
今回の場合、`'a`の型自身が`option`なので、何もしない`id`関数を渡せば`Some`に包まれた要素のみを含むリストが得られます。

`List`モジュールだけでなく、`Seq`モジュールや`Array`モジュールにも`choose`関数はあるので、このような操作がしたい場合は使うといいでしょう。

また、上の例で`Option.get`と何かの関数を合成していた場合は、`Option.map`関数にその関数を渡したものを`choose`に渡せばいいです。
例えば、

[code]

    let res =
      xs
      |> List.filter Option.isSome
      |> List.map (Option.get >> string)
    
[/code]

このコードは以下のように書き換えます。

[code]

    let res = xs |> List.choose (Option.map string)
    
[/code]


CC BY-SA 3.0
2014-12-19T05:17:25.807
2103
2014-12-19T05:17:25.807
4482
2102
answer