3つのモナド則の内、ようやく2つが理解できました。
(return x) >>= f == f x
以下のような DB を考えます。
db = [("alice", [("title", "Ms."), ("city", "Yokohama")]), ("bob", [("title", "Mr."), ("city", "Sapporo" )])]
"alice" の "city" が調べたいなら、こういう風にするでしょう。
lookup "alice" db >>= lookup "city" → Just "Yokohama"
左と右の lookup の使い方が違うのはなぜか常々疑問でした。左側では、db がいつのまにか Maybe モナドになっているのです。(ここは僕の思い違いでした。db は Maybe モナドになっていません。)
2つの lookup を同じように使うには、こう書きます。
return db >>= lookup "alice" >>= lookup "city" → Just "Yokohama"
これなら、return でモナドを作り、lookup を >>= で適応していくので、論理的には理解しやすいです。
しかし、いちいちこう書くのは面倒ですね。そこで、モナド則の出番です。
(return x) >>= f == f x
これは、return db >>= lookup "alice" と書く代わりに、lookup "alice" db と書けますよという意味だったんですね。
(m >>= f) >>= g == m >>= (\x -> f x >>= g)
これが理解できなかった理由が分りました。丸括弧が
- 結合力
- 関数
の 2 つの意味で使われています!
左は結合力の括弧で、右は関数の括弧ですね。右も結合力かと思って混乱していました。
>>= は左結合なので、
m >>= f >>= g
は、
(m >>= f) >>= g
のように処理されます。
その意味するところは、
なんですね。
m >>= return == m
この法則の意味するところが何なのか、分る人がいたら教えて下さい。do 記法の最後に return することと関係あるのかなぁ。。。
追記
m さんの言うことが分った気がしますので、追加します。
lookup "alice" の型は、[(String, a)] -> Maybe a です。だから、
lookup "alice" db
と書けるのは当然です。この結果は Maybe モナドです。
Maybe モナドの中身を取り出し、lookup "city" を適応し、Maybe モナドを返すには、当然こう書きます。
lookup "alice" db >>= lookup "city"
左右が対象でないのが気持ち悪いなら、モナド則を使ってこうも書けます。
return db >>= lookup "alice" >>= lookup "city"