Haskell:foldl'累加器参数
Posted
技术标签:
【中文标题】Haskell:foldl\'累加器参数【英文标题】:Haskell: foldl' accumulator parameterHaskell:foldl'累加器参数 【发布时间】:2012-06-20 01:22:02 【问题描述】:我一直在问一些关于严格性的问题,但我想我之前没记错。希望这更准确。
假设我们有:
n = 1000000
f z = foldl' (\(x1, x2) y -> (x1 + y, y - x2)) z [1..n]
不改变f
,我应该设置什么
z = ...
这样f z
不会溢出堆栈吗? (即无论 n 的大小如何,都在恒定空间中运行)
如果答案需要 GHC 扩展也可以。
我的第一个想法是定义:
g (a1, a2) = (!a1, !a2)
然后
z = g (0, 0)
但我不认为 g
是有效的 Haskell。
【问题讨论】:
【参考方案1】:因此,您的严格 foldl'
只会在折叠到 Weak Head Normal Form 的每个步骤中评估您的 lambda 的结果,即它仅在最外层的构造函数中是严格的。因此 tuple 将被评估,但是 inside 元组的那些添加可能会构建为 thunk。这个in-depth answer 实际上似乎在这里解决了您的确切情况。
W/R/T 你的g
:你正在考虑BangPatterns
扩展,看起来像
g (!a1, !a2) = (a1, a2)
在将 a1 和 a2 返回到元组之前,它会将 a1 和 a2 评估为 WHNF。
您要关心的不是您的初始累加器,而是您的 lambda 表达式。这将是一个不错的解决方案:
f z = foldl' (\(!x1, !x2) y -> (x1 + y, y - x2)) z [1..n]
编辑:注意到您的其他问题后,我发现我没有仔细阅读此问题。可以这么说,您的目标是拥有“严格的数据”。那么,您的另一个选择是创建一个在其字段上具有严格标签的新元组类型:
data Tuple a b = Tuple !a !b
然后,当您对Tuple a b
进行模式匹配时,将评估a
和b
。
无论如何,您都需要更改您的功能。
【讨论】:
【参考方案2】:如果不更改 f
,您将无能为力。如果 f
在配对类型中被重载,您可以使用严格配对,但就目前而言,您被锁定在 f
所做的事情中。编译器(严格性分析和转换)可以避免堆栈增长,但没有什么可以指望的。
【讨论】:
以上是关于Haskell:foldl'累加器参数的主要内容,如果未能解决你的问题,请参考以下文章