3

我一直在问一些关于严格性的问题,但我想我以前错过了分数。希望这更精确。

假设我们有:

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。

4

2 回答 2

9

因此,您的 strictfoldl'只会在折叠到Weak Head Normal Form的每个步骤中评估您的 lambda 的结果,即它仅在最外层的构造函数中是严格的。因此,将评估元组,但是元组的那些添加可能会构建为 thunk。这个深入的答案实际上似乎在这里解决了您的确切情况。

W/R/T your g:您正在考虑BangPatterns扩展,看起来像

g (!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,将对其进行评估。ab

无论如何,您都需要更改您的功能。

于 2012-06-20T03:12:23.707 回答
3

没有改变就什么都做不了f。如果f在对的类型中重载,您可以使用严格的对,但就目前而言,您被锁定在做什么f。编译器(严格性分析和转换)可以避免堆栈增长,但没有什么可以指望的。

于 2012-06-20T08:52:58.930 回答