モナドの合成

This entry was posted by on Thursday, 24 November, 2005
>「 >モナドのすべて >」を読んだら書いてあったので、文言はわかっていたのだけどイマイチ使いどころがよくわからないもののひとつが合成というやつで、これを軽々と使いこなせるとカッコいいのだろうなぁと朧げに思っていたのだけど。 > >ちょっとサンプル例題を思いついたのでメモ。 > >1行ずつ入力してもらって、入力が quit だったら、それまでの入力したものをリストにする処理を考える。 > >これはこう書ける。 > >import Control.Monad.List
inputList :: ListT IO String
inputList =
do s <- liftIO $ getLine
guard ("quit" /= s)
return s `mplus` inputList
> >なるほどなるほど。 > > >getLine は IO String になるので、これをうまく処理するのは面倒くさい。そのときのために ListT がある > > > >liftIO で「IO String から ListT IO String にする」 > > > >束縛した値は String として扱える > > > >"quit" と同等性を判断して guard しており、入力が quit だったら空リストにする > > > >さもなくば return して(1要素リストにし)、さらにもう一度 inputList したもの mplus (連結)している > > > >ゆえに「quitするまでは入力を促し、最終結果をリストにするモノ」ができあがる > > > > >という流れ。もちろん putStr を liftIO すればプロンプトが書けます。なるほど。 > >実際に計算するには次のようにする。 > >runListT inputList >>= print > >runListT は ListT m a => m > >実際には、 IO の値からリストを構成する場合ってあんまりないのかもしれないが、これはちょっとカッコいいと思った。なるほどこういうことなのかという。 > >ちなみにもし ListT がなければ、次のようになるだろう。 > >inputList :: IO [String]
inputList =
do s <- getLine
if s == "quit"
then return []
else inputList >>= return . (s:)
> >んーあんまりコード量は変わらなかった。処理が複雑化したら変わるかなあ(大差ない気もする)。 >

Comments are closed.