这不是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>
有一些 monad,mapM 可以处理无限的值列表,特别是惰性的 StateT monad 和 Identity,但它们是规则的例外。
通常,mapM/sequence/replicateM(不带下划线)是反模式,正确的解决方案是使用pipes,它允许您构建不尝试计算的有效流前面的所有结果。 The beginning of the pipes tutorial 更详细地描述了如何解决这个问题,但一般的经验法则是,任何时候你都可以写这样的东西:
example1 = mapM f xs
example2 = sequence xs
您可以将其转换为懒惰的Producer,只需将其转换为:
example1' = each xs >-> Pipes.Prelude.mapM f
example2' = each xs >-> Pipes.Prelude.sequence
使用上面的例子和Either,你会写:
>>> import Pipes
>>> let xs = each [0..] >-> mapM Right :: Producer Int (Either a) ()
然后你可以懒惰地处理流而不生成所有元素:
>>> Pipes.Prelude.any (> 10) xs
Right True