use*_*020 2 monads haskell list
我不知道Haskell,我只想玩它来学习它.我试图理解io,monads等,并在解释器(GHCi,版本7.10.2,WinGHCI)中写了这个:
Prelude> [1,1] >> "ok"
"okok"
Prelude> [1,1,1] >> "ok"
"okokok"
Prelude> [1..10] >> "ok"
"okokokokokokokokokok"
Prelude> [1] >> "ok" >> [1] >> "ok"
"okok"
Prelude> [1,2] >> "ok" >> [1,2] >> "ok"
"okokokokokokokok"
Prelude> [1..10] >> [1..10]
[1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10]
Run Code Online (Sandbox Code Playgroud)
小心解释一下?为什么列表中的元素数量会影响写入"ok"的次数(或者在最后一种情况下,是否写入数组的次数)?>>运算符不应该这样做,是吗?
lef*_*out 12
首先请注意,这与此无关IO.它与monad有关,但有一个非常具体的:monad列表.
instance Monad [] where
return x = [x]
f >>= xs = concat $ map f xs -- aka `(>>=) = concatMap`.
Run Code Online (Sandbox Code Playgroud)
最好知道列表推导,基本上是语法糖†:
[ result x y z | x <- bla, y <- foo x, z <- bar ]
Run Code Online (Sandbox Code Playgroud)
翻译成
bla >>=
\x -> foo x >>=
\y -> bar >>=
\z -> return (result x y z)
Run Code Online (Sandbox Code Playgroud)
现在,a>>b它只是一个捷径a >>= \_ -> b,即它忽略了LHS monadic动作中包含的值,但是"假装"在RHS中使用它们.所以,[1,1,1] >> "ok"是一样的
[ "ok" | _ <- [1,1,1] ]
Run Code Online (Sandbox Code Playgroud)
至少差不多......实际上这是相同的[1,1,1] >> return "ok",也就是说>> ["ok"],它会给予
["ok", "ok", "ok"]
Run Code Online (Sandbox Code Playgroud)
如果省略单例return,则每个"ok"都不会被包装在列表中,而是连接在一起,而是字符串本身都是由monadic绑定连接起来的.这就是你得到的"okokok".
† 等效的默认实现实际上有点不同,但通过-XMonadComprehensions扩展,列表推导确实以这种方式工作.