>>=
特定のモナドに対するの動作について学ぶために使用できる 4 つの情報源について説明します。
のタイプ>>=
の型>>=
は常に同じです。Monad
型クラスで指定されます。ドキュメントを参照してください。タイプは次のとおりです。
(>>=) :: forall a b. m a -> (a -> m b) -> m b
m
は、関心のある特定のモナドのプレースホルダーです。たとえば、リスト モナドの場合、型は>>=
次のとおりです。
(>>=) :: forall a b. [a] -> (a -> [b]) -> [b]
に置き換えm ...
ただけであることに注意してください[...]
。
モナドの法則
の実装は>>=
モナドごとに異なりますが、すべてのモナドはモナドの法則に従う必要があります。これらの法則は、Monad
型クラスのドキュメントで指定されています。ドキュメントをもう一度参照してください。法律は次のとおりです。
return a >>= k == k a
m >>= return == m
m >>= (\x -> k x >>= h) == (m >>= k) >>= h
したがって、特定のモナドの実装が何であれ、これらの法則を使用してコードを推論できます。たとえば、コードに法則の左側のようなコードが含まれている場合、そのコードを対応する法則の右側に置き換えることができ、動作は変更されません。
以下はモナド則の使い方の例です。次のコードを書いたとします。
foo = do
x <- bar
return x
ここでどのモナドが使われているかさえわかりませんが、do 記法が見られるので、いくつかのモナドがあることはわかります。モナドの法則を適用するには、次の呼び出しの do 表記を desugar する必要があります>>=
。
foo = bar >>= (\x -> return x)
\x -> return x
は just ( return
by η-reduction.
foo = bar >>= return
モナドの第 2 法則により、このコードは単に bar を呼び出すこととまったく同じことを意味します。
foo = bar
>>=
そのため、元の関数の は何も興味深いことをまったくできないように見えますfoo
。なぜなら、モナドの法則により、それを除外することが許されているからです。>>=
ここでは、どの特定のモナドが演算子を提供しているのかさえ知らずに、それを理解しました。
特定のモナドのドキュメント
特定のモナドに対するの動作について詳しく知る必要がある場合は>>=
、特定のモナドのドキュメントを参照してください。hoogleを使用してドキュメントを検索できます。たとえば、のドキュメントにStateT
は次のように記載されています。
return
関数は状態を変更せずに残しますが>>=
、最初の計算の最終状態を 2 番目の初期状態として使用します。
特定のモナドの実装
特定のモナドの実装についてさらに詳しく知りたい場合は、おそらく実際の実装を見なければなりません。instance Monad ...
宣言を検索します。たとえば、 の実装をStateT
見てください。リストモナドの実装は、このファイルのどこかにあります。検索するinstance Monad []
か、これを除いて見てください:
instance Monad [] where
m >>= k = foldr ((++) . k) [] m
m >> k = foldr ((++) . (\ _ -> k)) [] m
return x = [x]
fail _ = []
>>=
おそらく最も明白な定義ではないかもしれませんが、リストモナドを呼び出すとまさにそれが起こります。
概要
>>=
すべてのモナドは、とreturn
および モナド法則の型シグネチャを共有します。これらの制約とは別に、すべてのモナドは>>=
andの異なる実装を提供しreturn
ます。すべての詳細を知りたい場合は、instance Monad ...
宣言のソース コードを調べる必要があります。特定のモナドの使い方を学びたいだけなら、それに関するドキュメントを探してみてください。