Monad

今日は、Haskell の IOモナドが分からん、と噛み付かれた。大して分かっていない僕に聞くなよという感じだが、たぶん、いきなり IO から入るのがいけなくて、Maybe と List のモナドっぷりを味わうと、モナドという概念がとても自然に感じられるのではないかと思う。
この間のキップパズルでは Maybe モナドを使った。
http://d.hatena.ne.jp/nuc/20051103/p2

op2f x = case x of
               ADD -> (+)
               SUB -> (-)
               MUL -> (*)
               DIV -> (/)

eval2 :: Ctree -> Maybe Rational
eval2 (Number r) = Just r
eval2 (Cal (o,a,b)) = eval2 a >>= (\a0 -> eval2 b >>= (\b0 ->if o == DIV && b0==0 then  Nothing else Just$op a0 b0))
                       where op = op2f o

見れば見るほど悪いコードなので上に変えてみる。/0 がでてきたときには、その式の評価をなかったことにしたい。だが、普通に書けば、Exceptionが投げられる。


モナドというのは普段の世界から新しい世界を作る一つの道具。

普通の世界。というのは、この場合分数の世界。そこから、ぐっ、と引き出して新しい世界を作るのです。圏論の関手とされる。
Maybe a というのは、Just a と Nothing (aというのは決まった型)の和集合。
ここは
Maybe Integer
に関して考える。
Maybe a の元であるのは、Just 1000、 Just (-20)、 Just 0、 Nothing といったもの。さて。Integerの世界では、倍にするという演算がある。これを(2*)とでもしておこう。
すると

(2*) 1000 --> 2000
(2*) (-20) --> -40
(2*) 0 --> 0

になっている。
(2*) は Maybe世界に行っても、Just 1000 は Just 2000 に飛ばして欲しい。Nothing は Nothing に飛ばすのが妥当だろう。そうなると、

Just 1000 >>= return.(2*)
Nothing >>= return.(2*)

これで望みのものが出てくる。Listだともう少し役に立っている感じで、

[1,2,3,4,5] >>= return . (2*) >>= return . (1+)

で、[3,5,7,9,11]となる。
とか書いてみて、これってむしろ Functor の話な気がしてきた。もっと、モノイドでがしがし繋げるところをアピールすべきか。