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 の話な気がしてきた。もっと、モノイドでがしがし繋げるところをアピールすべきか。