関手・アプリカティブ関手・モナド
Functor
と Monad
はどちらもさらに型引数を待ち受ける型の演算を記述します。このことを理解するにあたって、Functor
は変換対象のデータを保持するコンテナを記述し、Monad
は副作用のあるプログラムのエンコードを記述するものと考えるのも1つの手でしょう。しかし、この理解は不完全です。というのも、 Option
は Functor
と Monad
の両方のインスタンスを持ち、オプショナルな値と値の返却に失敗するかもしれない計算を 同時に 表現するからです。
データ構造の観点から、Option
はnullable型や高々1個の要素しか保持できないリストのようなものに少し似ています。制御構造の観点からは、Option
は結果を伴わずに早期リターンするかもしれない計算を表現します。通常、Functor
インスタンスを使うプログラムは Option
の使い道をデータ構造としてみなす場合が最も簡単であり、一方で Monad
インスタンスを使うプログラムも Option
の使い道を早期の失敗を許可するものとみなす場合が最も簡単ですが、これらの観点両方を流暢に使えるようになることは関数型プログラミングの達人になるためには重要なポイントです。
関手とモナドの間には深い関係があります。実は すべてのモナドは関手になります 。言い換えると、すべての関手がモナドにはならないため、モナドの抽象化は関手の抽象化よりも強力であるということです。さらに、両者の間には アプリカティブ関手 (applicative functor)と呼ばれる抽象化が存在します。これもまた多くの興味深いプログラムを書くにあたって十分な力を持ち、Monad
のインタフェースを使えないライブラリでも使うことができます。型クラス Applicative
はアプリカティブ関手のオーバーロードされた演算を提供します。すべてのモナドはアプリカティブ関手であり、またすべてのアプリカティブ関手は関手ですが、これらの逆は成り立ちません。