小编bue*_*hse的帖子

无可辩驳的模式在递归时不会泄漏内存,但为什么呢?

mapAndSum代码块下面的所有方式结合功能mapsum(不去管另一个sum是在主函数中应用,它只是用来使输出紧凑型).它map是懒惰地计算的,而sum使用累积参数计算.这个想法是,结果map可以在没有完整列表的情况下被消费,并且(仅)之后sum可以"免费"获得.main函数表示调用时我们遇到了无法反驳的模式问题mapAndSum.让我解释一下这个问题.

根据Haskell标准,无可辩驳的模式示例let (xs, s) = mapAndSum ... in print xs >> print s被翻译成

(\ v ->    print (case v of { (xs, s) -> xs })
        >> print (case v of { (xs, s) -> s }))
$ mapAndSum ...
Run Code Online (Sandbox Code Playgroud)

因此,两个print调用都带有对整个对的引用,这导致整个列表保存在内存中.

我们(我的同事Toni Dietze和我)使用明确的case陈述解决了这个问题(比较"坏"与"好2").顺便说一句,发现这一点花了我们相当多的时间..!

现在,我们不理解的是双重的:

  • 为什么mapAndSum首先工作?它还使用无可辩驳的模式,因此它也应该将整个列表保留在内存中,但显然不会.并且转换let为a case将使该函数表现为完全不受欢迎(到堆栈溢出的程度;没有双关语意图).

    我们看了GHC生成的"核心"代码,但就我们所能解释的那样,它实际上包含了与let上面相同的翻译.所以在这里没有任何线索,而是更多的混乱.

  • 为什么"不好?" 关闭优化时工作,但打开优化时不工作? …

haskell lazy-evaluation ghc accumulator space-leak

14
推荐指数
1
解决办法
596
查看次数

标签 统计

accumulator ×1

ghc ×1

haskell ×1

lazy-evaluation ×1

space-leak ×1