这不是Cont
monad的缺陷,而是sequence
。你可以得到类似的结果Either
,例如:
import Control.Monad.Instances()
xs :: [Either a Int]
xs = map Right [0..] -- Note: return = Right, for Either
ys :: Either a [Int]
ys = sequence xs
你无法找回ys
任何元素,直到它计算整个列表,这将永远不会发生。
另外,还要注意:sequence (map f xs) = mapM f xs
,所以我们可以简化这个例子:
>>> import Control.Monad.Instances
>>> mapM Right [0..]
<Hangs forever>
有几个单子,其中mapM
将值的无限清单开展工作,特别是懒惰StateT
单子和Identity
,但他们是规则的例外。
一般来说,mapM
/sequence
/replicateM
(不带尾随下划线)是反模式和正确的解决办法是使用pipes
,它允许你创建不尝试计算所有结果前面effectful流。 The beginning of the pipes
tutorial介绍了如何在更详细解决这个问题,但一般的经验法则是,任何时候,你写的东西,如:
example1' = each xs >-> Pipes.Prelude.mapM f
example2' = each xs >-> Pipes.Prelude.sequence
:
example1 = mapM f xs
example2 = sequence xs
你可以只将其转化为改造成一个懒惰Producer
使用与Either
上面的例子,你可以这样写:
>>> import Pipes
>>> let xs = each [0..] >-> mapM Right :: Producer Int (Either a)()
然后你就可以懒惰地处理日而不产生所有元件E流:
>>> Pipes.Prelude.any (> 10) xs
Right True
可能的重复[为什么Haskell序列函数不能懒惰或为什么递归单子函数不能懒惰](http://stackoverflow.com/questions/14494648/why-the-haskell-sequence-function - 懒惰或为什么递归一元函数) –