haskell - 某些向量运算中没有惰性

标签 haskell

这段代码尝试急切地计算[1..],这会导致无限循环。

import qualified Data.Vector as V

infiniteLoop = V.zipWith (+) (V.fromList [1..4]) (V.fromList [1..])

为什么会这样?

最佳答案

使用-O2编译。

...好吧,这仅在某些情况下有效。

在您的未优化构建中,首先构建通过fromList创建的两个向量。由于向量是脊椎严格的(并且未装箱的向量是超严格的),因此这将失败,因为您无法构造无限大小的向量。

如果使用-O2进行编译,流融合就会发挥作用。现在,所有中间向量(来自 fromList 的向量)根本没有被创建。由于 zipWith 在第一次数据提供完成后停止,因此您现在有了一个终止函数。

但一般来说:不要在向量运算中使用无限大小的供应,函数的语义现在取决于您的优化级别,这是不好的。

原文"stream fusion" paper描述从列表到流的切换,以及再次返回列表的切换。为了简化起见,您可以将列表视为向量(因为向量添加了一堆附加内容,例如内存分配、单子(monad)行为等)。

一般来说(并且更加简单),重写规则用于在内部将向量表示为流,从而实现融合,然后流又转回向量。

关于haskell - 某些向量运算中没有惰性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24584986/

相关文章:

haskell - 如何在let绑定(bind)中添加类型注释

haskell - 'do' block 内的守卫 - haskell

haskell - 递归还是列表理解?

Haskell 函数依赖 a b -> c 取决于 c?

haskell - Vinyl:使用需要所有字段共享约束的函数进行 rtraverse

haskell - Haskell 记录中的名称冲突

http - 在 Haskell 中发送带有 header 的 GET 请求

变量类型签名的 Haskell 困难

haskell - 从字符转换为Unicode数字时出错

haskell - 惰性和函数组合(haskell、erlang)