Tuesday, 16 July 2013

Monad の合成

学生の(いや、社会人でもそうかも知れないけど)デバッグを見てると、大半は、printf debug 。まぁ、一番お手軽。それに、source code debugger が使える状況は、かなりラッキーなわけだし。

なんですが、Haskell は PrtStrLn とかを任意のところに挟むわけにはいきません。こいつは IO Monad なので。 例えば

fact1 0 = return 1
fact1 n = do
putStrLn (show n)
c <- fact1 (n -1)
return ( n * c )

とかは、問題なく動くんだけど、自作の Monad をはさむと、

fact4 0 = return 1
fact4 n = do
putStrLn (show n)
c <- fact2 (n -1)
Tn [c] ( n * c )

これは型エラー。これは Monad T1 を返す関数なんだけど、 putStrLn (show n) は IO を返すので、それが衝突してしまう。

mylift m =
Tn [] ( do
c <- m
putStrLn (show c)
return c
)

fact2 0 = return 1
fact2 n = do
mylift $ putStrLn (show n)
c <- fact2 (n -1)
Tn [c] ( n * c )

とすると、mylift が IO a -> T1 なので、型は合います。合いますが、IO Monad を誰も触ってくれないので印字してくれません。これは誰も見ない printf だから消されてしまったみたいなものだな。

つまり、IO Monad と T1 Monad が合成できれば良いわけね。調べてみると、

http://www.slideshare.net/tanakh/monad-tutorial

http://d.hatena.ne.jp/m-hiyama/20070507/1178496486

全然自明ではないらしい。Haskell 内蔵の Error とか Maybe とかには、ErrorIO とか MaybeIO とかあるらしい。

自作 Monad 用には、MonadIO とか MonadTrans とかあるらしいのだけど、

* 使い方がまったくわかりません

うううう。困ったものだ。Haskell library の source を見てみるのだが、どうにもこうにも。困ったものだ。まぁ、時間が解決するとは思いますが。

No comments: