我在 Haskell 中与惰性求值的斗争之一是难以推理内存使用情况。我认为复制 thunk 的能力会让我更容易做到这一点。这是一个例子。
让我们创建一个非常大的列表:
let xs = [1..10000000]
现在,让我们创建一个坏函数:
bad = do
print $ foldl1' (+) xs
print $ length xs
如果没有优化,这会占用几十 MB 的内存。垃圾收集器无法在折叠期间释放 xs,因为稍后计算长度时需要它。
是否可以像这样重新实现此功能:
good = do
(xs1,xs2) <- copyThunk xs
print $ foldl1' (+) xs1
print $ length xs2
现在,xs1 和 xs2 将表示相同的值,但在内存中也相互独立,因此垃圾收集器可以在折叠期间释放内存,从而防止内存浪费。(我认为这会稍微增加计算成本?)
显然在这个简单的例子中,重构代码可以很容易地解决这个问题,但是如何重构似乎并不总是很明显。或者有时重构会大大降低代码的清晰度。