Option型のmapとbindの使い分け

F#のOptionにはmapとbindの関数があります。この2つの関数は値がSomeの場合に、値を変換するという点では同じですが、変換に使用する関数の戻り値の型が異なります。

int option がある時、

  • map は int -> T の関数を受け取ります。
  • bind は int -> T option の関数を受け取ります。

※Tは任意の型です。

以下の例ではmapを使ってOptionの数値からOptionの文字列へ変換しています。mapはSomeをアンラップして値を取り出し、引数で受けた関数を使って値を変換し、結果を再びSomeでラップします。

let age = Some 25
let message = age |> Option.map (fun x -> sprintf "%i years old" x)
// Some(25 years old)

一方でbindはSomeをアンラップして値を取り出し、引数で受けた関数に渡して値を変換するまではmapと同じです。異なるのは、変換後の値がOptionであり、その値をそのまま返すという点です。mapのようにSomeで再びラップしません。以下の例もOptionの数値からOptionの文字列へ変換していますがmapの動作と異なり、引数がSomeの場合でも戻り値がNoneになっています。

let age = Some 25
let ageWhen1990 age = if age < 35 then None else Some (35 - age)
let message = age |> Option.bind ageWhen1990
// None

使い分けとしては、mapは変換に必ず成功する場合に使用すると良く、bindは変換に失敗する可能性がある時に使えば良さそうです。