OCamlでElmのMaybe.map2を実装
OCamlには標準でOption.map
関数が有ります。
コレは、Optionな値一つと、それを処理する関数f
を渡してあげることで、map関数はOptionな値の中身を取り出して、関数f
にその値を渡して実行してくれる、というものです。
None
が渡されれば渡した関数f
は実行されずにNoneがそのまま返されます。
渡した関数f
の実行結果はOption.map
関数によって自動的にSome
に包まれます。
関数内で態々Optionの中身をアンラップしなくて良いのでコードの見通しが良くなりますね!
utop # Some 10 |> Option.map (fun v -> v + 1) |> Option.map (fun v -> v * 2);;
- : int option = Some 22
utop # None |> Option.map (fun v -> v + 1) |> Option.map (fun v -> v * 2);;
- : int option = None
Option.map
関数の使いどころは、最初に「有るかもしれないし、無いかもしれない」というデータを得て、もしデータが存在している(Some
)ならそのデータを使って処理を継続していく、途中で自分からOptionな値を返す必要がない、という普通のロジックの場合です。
(もし途中でSome
かNone
を返したい場合にはOption.bind
を使います)
しかし、map関数が受け取るのはあくまで一つのOptionの値のみです。 例えば2つのOptionな値を渡すことはできません。
Elmではそのために、Maybe.map2
という関数が有ります。
OCamlには標準ではそのような関数は存在しませんが、以下のように簡単に自分で実装することが可能です。
utop # let option_map2 f a b =
match (a, b) with
| (None, Some _)
| (Some _, None)
| (None, None) -> None
| (Some v1, Some v2) -> Some (f v1 v2);;
val option_map2 : ('a -> 'b -> 'c) -> 'a option -> 'b option -> 'c option =
<fun>
実際に試すと以下のようになります。
utop # option_map2 (fun a b -> a + b) None None |> option_map2 (fun a b -> a * b) (Some 10);;
- : int option = None
utop # option_map2 (fun a b -> a + b) None (Some 1) |> option_map2 (fun a b -> a * b) (Some 10);;
- : int option = None
utop # option_map2 (fun a b -> a + b) (Some 1) None |> option_map2 (fun a b -> a * b) (Some 10);;
- : int option = None
utop # option_map2 (fun a b -> a + b) (Some 1) (Some 2) |> option_map2 (fun a b -> a * b) (Some 10);;
- : int option = Some 30
非常に便利になりました。
公開日:2020/07/10