モナドって何だろうかということを昔考えていたときのメモが見つかったので、以下にはりつけておこうと思います。何かの役に立てば。
@s_h_i_g_e_chan さんと勉強会をしました。前回の勉強会で疑問だったモナドの別の例を学ぶためです。
結局モナドってなんなんだろうと思って図にしてみたが、Haskell文法以上の何かにさえなりませんでした。。。Haskell文法以上に抽象化した表現はできないということでしょうか。
まず↓のようなdo文があったとしましょう。
↑を>>=に変換すると↓のようになるわけです。
ここまではどのようなモナドでも同じ形を取ります。というかHaskell文法そのものです。
例として以下のようなdo文を例にして、もっと詳しく処理内容を見てみましょう。
-- リストモナド定義 instance Monad [] where m >>= f = concatMap f m return x = [x] fail s = [] instance MonadPlus [] where mzero = [] mplus = (++) -- do文の例 do x <- [1,2,3] y <- [3+x,6+x] [x,y]
どのようなモナドかわかれば、具体的な実行イメージはできます。
前回の勉強会ではdo文が一行実行したら次の行を実行していっているように見えましたが、リストモナドは使い方によってはツリー状に次の行が分裂して実行されていくように見えます。
なぜそのようなことになるかというと、>>=がconcatMapになっているためです。concatMapは「第一引数の関数を第二引数の要素それぞれに適用して、その結果のリストをconcatする」ように動作するため、第一引数で指定された関数(この場合はλxだったりλyだったり)がリストの個数だけ実行されます。
。。。なんか言えば言うほど当たり前のことしか説明できないのですが、>>=によってdo文の次の行がどのように実行されるのか、いかようにも決められるワケです。それでもdo文のλスコープによって計算は前後に分離されます。do文が出現したら順序制御したいんだなって思えばいいのかな?
そーゆーワケでリスト内包表記はリストモナドのdo文です。なるほどです。
-- do文で do x <- [1,2,3] y <- [3+x,6+x] return (x,y) -- リスト内包表記で [(x,y) | x <- [1,2,3], y <- [3+x,6+x]]
.