do記法を使って次のように書くことができて,不思議だと思った.
test = do
a <- [1,2]
b <- [3,4]
[(a,b)]
main = print test
実行結果
[(1,3),(1,4),(2,3),(2,4)]
どういうことなのか,自分なりに納得したいと思ったので,調べた.以降,次のコードの動きを説明する.
test = do
[1,2]
[3,4]
main = print test
実行結果
[3,4,3,4]
do記法のルール
Haskll 2010 Language Reportの3.14によると,eが式のときは次の決まりになっている.
-
do {e}
はe
になる -
do {e;stmts}
はe >> do {stmts}
になる
以上の決まりによりtest
は次のものと同じ
test = [1,2] >> [3,4]
モナドの>>
演算子
ライブラリの説明によると,>>
は次のように定義されている.
class Applicative m => Monad m where
(>>) :: m a -> m b -> m b
m >> k = m >>= \_ -> k
m
の値を文脈と呼ぶことにすると,>>
は文脈を捨てる感じ.モナドは>>=
(bind)とreturn
しかないので,>>
では>>=
を使って文脈を捨てる必要があった.
この定義を使うとtest
は次のようになる.
test = [1,2] >>= \_ -> [3,4]
リストモナドの>>=
ライブラリの説明によると,リストの>>=
の定義は次の通り.
instance Monad [] where
xs >>= f = [y | x <- xs, y <- f x]
この文法はList comprehensionで,Haskll 2010 Language Reportの3.11で解説されている.
この定義を使うとtest
は次のようになる.
test = [y | x <- [1,2], y <- [3,4]]
以上でtest
は[3,4,3,4]
になる.