haskell - 为什么`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]
不幸的是,我不能从那个供应中得到任何东西。
当我替换action
并return
尝试不同的 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]
?
解决方案
这在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
本质上是一样的。
推荐阅读
- c# - 将文本时间转换为日期时间变量c#
- code-snippets - 在自定义 Emmet 片段中重复光标文本
- python - 在 python 中将 2x16 数据帧转换为 4 x 4 矩阵
- python - Django表单提交不刷新
- javascript - 获取天气预报 api javascript 时出现未定义的错误
- python - Python 请求在 __doPostBack 之后获得 __VIEWSTATE 和 __EVENTVALIDATION
- python - 在 Jupyter 笔记本上使用 read_csv 时找不到文件错误
- r - 重新编码和折叠多个二进制编码的列
- unicode - 如何在 VB6 中读取/写入具有 Unicode 文件名的二进制文件
- vba - 下面的 StrComp 代码有什么问题