モナドを使うのに圏論の知識なんて不要だし、モナド則なんか意識する必要はない、というのはその通りだと思う。ぼく自身、圏論にはあまり興味は無いし深入りする気はないのだが、Haskellの珍妙な演算子と珍妙な関数名と謎のエラーメッセージを理解してコンパイルの通るコードを書くためには、やはりモナドについて基本的な理解が必要だと感じた。(C言語ではじめてポインタを使ったときの感覚に近いかも。)
return と >>= に関するモナド則
Haskellにおけるモナド則とは、return と >>= (bind) に関するルールであり、return の左単位律と右単位律、および >>= の結合律である。しかし、単位律も結合律も非対称な形になり、いまひとつ分かりにくい。具体例として、Maybeモナドの例を図示する。
斜め上に上がる関数 f の入り口を持ち上げて真横にして、x を持ち上げた m x を渡すのは、
関数 f に x に渡すのと同じ。
まっすぐ持ち上げる関数である return の入り口を持ち上げると、
何もせずに素通りする関数になる。
① 関数 f の入り口を持ち上げて真横にして m x を渡した戻り値を、
関数 g の入り口を持ち上げて真横にして渡した戻り値
② 関数 g の入り口を持ち上げて真横にして 関数 f の出口とつなげた関数の
入り口を持ち上げて真横にして m x を渡した戻り値
①と②は等しい。
return と join に関するモナド則
いっぽう、圏論におけるモナド則は、Haskell の言葉でいうと return と join に関するルールである。こちらのほうが見た目にはすっきりしていて分かりやすい。ただ、これが単位律なのか?結合律なのか?といわれるとちょっと首をかしげたくなる。具体例として、Listモナドの例を図示する。
モナドの内側に一皮かぶせてから一皮むいても、元のモナドと同じ。
モナドの外側に一皮かぶせてから一皮むいても、元のモナドと同じ。
三重のモナドを内側から一皮むいてさらに一皮むいても、
三重のモナドを外側から一皮むいてさらに一皮むいても、同じ一重のモナドになる。