首页 > 解决方案 > 为什么`fmap(取10)。序列 。fmap return $ [1..] :: m [Int]` 仅适用于某些 monad?

问题描述

我希望拥有的是无穷无尽的随机或非确定性数字。我继续这样编程:

supply :: Monad m => (Int -> m Int) -> m [Int]
supply action = sequence . fmap action $ [1..]

action要么是要么\n -> randomRIO (1, n)\n -> [1.. n]

不幸的是,我不能从那个供应中得到任何东西。

当我替换actionreturn尝试不同的 monad 时,我发现了这一点Identity并且Reader可以工作,但在这种情况下它们并不是那么有用。

λ flip runReader 13 (fmap (take 10) (supply return))
[1,2,3,4,5,6,7,8,9,10]
λ runIdentity (fmap (take 10) (supply return))      
[1,2,3,4,5,6,7,8,9,10]
λ [] : (fmap (take 10) (supply return))
[[]^CInterrupted.
fmap (take 10) (supply return) :: IO [Int]
^CInterrupted.

某些单子在排序时具有这种悬挂质量一定是有原因的,但我不明白。这是一个严格的问题吗?例如,此 Identity 和列表​​实例之间的标志性区别是什么?为什么我可以有一个流组装出来Identity i,但不是同样琐碎的单例列表[i]

标签: haskell

解决方案


这在IO. 您正在构建一个无限的IO操作列表,然后sequence将其转换为单个操作,该操作通过执行所有底层操作IO来生成整个列表。它必须立即执行所有操作,因为它们可能会产生副作用。显然,这永远不会结束。如果你想让它工作,你需要类似.unsafeInterleaveIO

这个[]例子有点微妙。以下内容也将挂起:

> map (take 10) $ transpose [[x] | x <- [1..]]
[[1,2,3,4,5,6,7,8,9,10]^CInterrupted.

transpose必须遍历整个无限列表,寻找其中可能包含两个元素的任何内容来决定是否应该有第二行。 sequence本质上是一样的。


推荐阅读