>>操作员 - 哈斯克尔的穷人循环?

时间:2015-08-06 06:17:47

标签: list haskell monads

我不知道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]

小心解释一下?为什么列表中的元素数量会影响写入“ok”的次数(或者在最后一种情况下,是否写入数组的次数)? >>算子不应该这样做,是吗?

1 个答案:

答案 0 :(得分:12)

首先请注意,这与IO没有任何关系。它与monad有关,但有一个非常具体的:monad列表。

instance Monad [] where
  return x = [x]
  f >>= xs = concat $ map f xs   -- aka `(>>=) = concatMap`.

最好知道 list comprehensions ,它基本上是语法糖

[ result x y z | x <- bla, y <- foo x, z <- bar ]

转换为

bla >>=
   \x -> foo x >>=
            \y -> bar >>=
                     \z -> return (result x y z)

现在,a>>b只是a >>= \_ -> b的捷径,即它忽略了LHS monadic动作中包含的值,但是“假装”在RHS中使用它们。因此,[1,1,1] >> "ok"

相同
[ "ok" | _ <- [1,1,1] ]

至少几乎......实际上与[1,1,1] >> return "ok"相同,即>> ["ok"],这将给出

["ok", "ok", "ok"]

如果省略单例return,则每个"ok"都不会被包含在列表中,而是连接在一起,而是字符串本身都是由monadic绑定连接起来的。这就是你如何得到"okokok"

等效的默认实现实际上有点不同,但使用-XMonadComprehensions扩展名,列表推导确实以这种方式工作。