それは混乱になることの一つは、そのような「人気」の機能であるbind
と<*>
指向実践しています。しかし、概念を理解するには、最初に他の機能を見るほうが簡単です。モナドは、他の関連する概念と比較して少し誇張されているため、際立っていることにも注意する価値があります。そこで、代わりにファンクターから始めます。
ファンクターは関数を提供します(Haskell表記)fmap :: (Functor f) => (a -> b) -> f a -> f b
。つまりf
、関数を持ち上げることができるコンテキストがあります。あなたが想像できるように、ほとんど何でもファンクターです。リスト、多分、いずれか、関数、I / O、タプル、パーサー...それぞれが値を表示できるコンテキストを表します。そのため、を使用するfmap
か、インラインバリアントを使用して、ほぼすべてのコンテキストで機能する非常に汎用性の高い関数を作成できます<$>
。
コンテキストで他にやりたいことは何ですか?2つのコンテキストを組み合わせることができます。したがってzip :: [a] -> [b] -> [(a,b)]
、たとえば次のような一般化を取得することができますpair :: (Monoidal f) => f a -> f b -> f (a,b)
。
しかし実際にはさらに便利なので、Haskellライブラリは代わりにを提供しますApplicative
。これはFunctor
and Monoidal
とAndの組み合わせであり、Unit
実際にコンテキストの「内部」に値を置くことができることを追加するだけですunit
。
作業中のコンテキストに関するこれら3つのことを述べるだけで、非常に汎用的な関数を作成できます。
Monad
あなたはその上に述べることができるもう一つのことです。私が前に言及しなかったことは、2つのコンテキストを結合する2つの方法がすでにあるということです:pair
それらだけでなく、スタックすることもできます。例えば、リストのリストを持つことができます。I / Oコンテキストでの例は、ファイルから他のI / Oアクションを読み取ることができるI / Oアクションです。したがって、typeがありFilePath -> IO (IO a)
ます。実行可能な関数を取得するために、そのスタックをどのように取り除くことができますIO a
か?そこでMonad
s join
が登場し、同じタイプの2つのスタックされたコンテキストを組み合わせることができます。同じことはパーサーにも当てはまるかもしれません。たぶんbind
、より実用的な方法です。join
したがって、モナドコンテキストは4つのものを提供するだけでよく、I / O、パーサー、障害などのために開発されたほぼすべての機械で使用できます。