あなたの問題は価値観に集中しすぎていると思います。モナドは型構築子であり、値の数や種類には関係なく、コンテキストのみに関係します。
Aは である場合もMaybe a
あれば、a
何もない場合もあります。簡単です。あなたはそれを正しく観察しました。
AnEither String a
は some a
、または a の形式の情報String
(たとえば、なぜ計算がa
失敗したか) のいずれかです。
最後に[a]
、不明な数のa
s (またはまったくない) です。これは、あいまいな計算、または複数の結果 (2 次方程式など) の結果である可能性があります。
ここで、 の解釈のため(>>=)
に、モナドの本質的な性質 (圏論者による定義方法) を知っておくと役に立ちます。
join :: m (m a) -> m a.
とともにfmap
、(>>=)
の観点から書くことができますjoin
。
join
つまり、次のことを意味します:同じコンテキストに再び配置されたコンテキストは、 (このモナドに対して) 同じ結果の動作を持ちます。
については、これは非常に明白ですMaybe (Maybe a)
。本質的に何かがJust (Just x)
、 またはNothing
、 またはJust Nothing
である可能性があり、 と同じ情報を提供しますNothing
。したがって、を使用する代わりに、情報を失うことMaybe (Maybe a)
はMaybe a
ありません。つまりjoin
、「より簡単な」コンテキストに変換されます。
[[a]]
やや難しいですが、それほどではありません。基本的に、複数/あいまいな結果から複数/あいまいな結果が得られます。良い例は、二次方程式を解くことによって求められる 4 次多項式の根です。最初に 2 つの解が得られ、それぞれから別の 2 つの解を見つけることができ、結果として 4 つの根が得られます。
しかし要点は、あいまいなあいまいな結果について話すか、あいまいな結果について話すかは問題ではないということです。常に「あいまいな」コンテキストを使用し、複数のレベルをjoin
.
そして(>>=)
、リストの場合は次のようになります。あいまいな関数をあいまいな値に適用します。
squareRoots :: Complex -> [Complex]
fourthRoots num = squareRoots num >>= squareRoots
として書き換えることができます
fourthRoots num = join $ squareRoots `fmap` (squareRoots num)
-- [1,-1,i,-i] <- [[1,-1],[i,-i]] <- [1,-1] <- 1
あなたがしなければならないのは、可能な値ごとに可能なすべての結果を見つけることだけだからです。
これが がリスト用である理由join
でconcat
あり、実際には
m >>= f == join (fmap f) m
どのモナドでも保持する必要があります。
についても同様の解釈ができますIO
。副作用 ( IO (IO a)
) を持つこともできる副作用のある計算は、本質的には副作用のあるものにすぎません。