为什么`fmap(需要10个)。序列 。fmap return $ [1 ..] :: m [Int]`仅适用于某些单子吗?

Ign*_*rov 2 haskell

我希望有无数的随机或不确定的数字。我继续像这样编程:

supply :: Monad m => (Int -> m Int) -> m [Int]
supply action = sequence . fmap action $ [1..]
Run Code Online (Sandbox Code Playgroud)

-使用action为任一或\n -> randomRIO (1, n)\n -> [1.. n]

不幸的是,我无法从该供应中获取任何东西。

当我换成actionreturn和尝试了不同的单子,我发现IdentityReader工作,但他们不是在这种情况下非常有用。

? 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.
Run Code Online (Sandbox Code Playgroud)

有些单子在排序时具有这种挂起的品质,这一定是有原因的,但是我看不到。这是严格性问题吗?例如,此Identity和list实例之间的标志区别是什么?为什么我可以从Identity i单个但不重要的单例列表中组装出一个流[i]

Chr*_*ith 5

这不适用于不足为奇IO。您要建立一个无限的IO动作列表,然后sequence将其变成一个IO动作,通过执行所有基础动作来生成整个列表。它必须立即执行所有操作,因为它们可能会有副作用。显然,这将永远不会结束。如果您希望此方法有效,则需要类似的内容unsafeInterleaveIO

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

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

transpose必须遍历整个无限列表,寻找其中可能包含两个元素的任何元素,以决定是否应该有第二行。 sequence基本相同。