モナド (プログラミング)
bind 演算子 >>= を直接使ってプログラムを書くのがよい場合もあるが、典型的にはdo記法 (OCamlでは perform記法、F#ではコンピュテーション式)を使用し、命令型言語のような見た目にできる。コンパイラはdo記法の式を >>= を使ったものに変換する。例えば
を変換した結果は以下となる。
リストモナドの実装を見てみよう。リストにマップを行い結合を行う(平らにする)この関数は concatMap とも呼ばれる。
よって、以下のような変形が行われて、それぞれの式はすべて等価である。
リスト[1..2]は使われないことに注意しよう。左矢印をつけないことで、連鎖した関数は引数を無視するように変換されて、値ではなくモナド的な構造だけが問題になることを示すことができる。例えば、状態モナドで値を生成せずに状態だけを変化させるようなときに使われる。do記法は >>= の単なる構文糖衣であるので、どんなモナドに対しても使うことができる。
Maybeモナドの値を安全に割り算する以下の定義も等価である。
同様にF#ではコンピュテーション式を使うことができる。
このmaybeブロックは構文糖衣であり、以下の式に変換される。
数学的には、liftM2 は次のように定義される。
liftM2 : ∀ M : monad , ( A 1 → A 2 → R ) → M A 1 → M A 2 → M R = {\displaystyle {\text{liftM2}}\colon \forall M\colon {\text{monad}},\;(A_{1}\to A_{2}\to R)\to M\,A_{1}\to M\,A_{2}\to M\,R=} o p ↦ m 1 ↦ m 2 ↦ bind m 1 ( a 1 ↦ bind m 2 ( a 2 ↦ return ( o p a 1 a 2 ) ) ) {\displaystyle op\mapsto m_{1}\mapsto m_{2}\mapsto {\text{bind}}\;m_{1}\;(a_{1}\mapsto {\text{bind}}\;m_{2}\;(a_{2}\mapsto {\text{return}}\;(op\,a_{1}\,a_{2})))}
関数型プログラミングにおいて、モナドはプログラムを構造化するための汎用的な抽象概念である。対応したプログラム言語では、ボイラープレート的なコードでもモナドを使って除去することが可能となる。これはモナドが、特定の形をした計算を表すデータ型と、それに関する生成と合成の2つの手続きを提供することによって実現されている。生成は任意の基本型の値をモナドに包んでモナド値を生成する手続きであり、合成はモナド値を返す関数(モナド関数)たちを合成する手続きである。
広い範囲の問題をモナドを使うことで単純化できる。例えば、Maybeモナドを使えば未定義値への対処が簡単になり、Listモナドを使えばリストに入った値を柔軟に扱うことができる。複雑に組み合わさった関数は、モナドを使えば、補助データの管理や制御構造や副作用を除去した簡単なパイプライン構造に置き換えることができる。
モナドの概念や用語は圏論から来ている。圏論においては、モナドは追加の構造を持つ関手として定義されている。1980年代の後半に研究され始め、1990年代前半には、一見無関係な計算機科学上の問題がモナドによって統一的で関数的にモデル化できることが分かってきた。圏論はモナドの満たすべき形式的な条件を与え、これはモナド則と呼ばれている。モナド則はモナド的なコードの形式的検証にも使用可能である。
ある種の計算では、その計算の意味をモナドで明確に表現できることを利用して、プログラム言語の便利機能の実装にモナドを使うことができる。Haskellのように、標準ライブラリですでに汎用のモナド構造といくつかのインスタンスを定義している言語もある。