我希望拥有无穷无尽的随机或不确定数字。我继续像这样编程:
supply :: Monad m => (Int -> m Int) -> m [Int]
supply action = sequence . fmap action $ [1..]
-action
为\n -> randomRIO (1, n)
或\n -> [1.. n]
不幸的是,我不能从那笔物品中拿走任何东西。
当我将action
替换为return
并尝试使用不同的monad时,我发现Identity
和Reader
可以工作,但在这种情况下它们并没有那么有用。 / p>
λ 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和list实例之间的标志区别是什么?为什么我可以用Identity i
组成一个流,却不能用类似的琐碎的单例列表[i]
组成一个流?
答案 0 :(得分:5)
这在IO
中不起作用也就不足为奇了。您正在建立IO
动作的无限列表,然后sequence
将其变成单个IO
动作,该动作通过执行 all 来生成整个列表基本动作。它必须立即执行所有操作,因为它们可能会有副作用。
显然,这将永远不会结束。如果您希望这样做,则需要类似unsafeInterleaveIO
的东西。
[]
示例更加微妙。以下内容也会挂起:
> map (take 10) $ transpose [[x] | x <- [1..]]
[[1,2,3,4,5,6,7,8,9,10]^CInterrupted.
transpose
必须遍历整个无限列表,寻找其中可能包含两个元素的任何元素来决定是否应该有第二行。 sequence
基本相同。