list ->> 运算符——Haskell 中的穷人循环?

标签 list haskell monads

我不了解 Haskell,我只是想通过玩弄它来学习它。我试图理解 io、monad 等,并在解释器(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”的次数(或者在最后一种情况下,会影响写入数组的次数)? >> 运算符不应该这样做,是吗?

最佳答案

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

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

最好了解列表理解,它基本上是语法糖:

[ 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 bind 连接.这就是您如何获得 "okokok"


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

关于list ->> 运算符——Haskell 中的穷人循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31848124/

相关文章:

python - 嵌套列表理解

同时交叉和添加列表元素的 Pythonistic 方法

haskell - 为n个不同版本构建haskell包

haskell - Applicative 的 ghci 特例?

python - 从 python 字典列表中删除引号

python - (几乎)从列表中均匀选择项目

haskell - MonadFix 严格的语言

haskell - RankNTypes : apply the same function to pairs of different types

haskell - 自由单子(monad)和自由操作

syntax - Haskell:我可以在带有绑定(bind)运算符(>>=)的 block 之后使用 where 子句吗?