为什么 foldr 应用于两个参数都严格的函数不会导致堆栈溢出?

Why does foldr applied to a function strict in both arguments not cause a stack overflow?

我想知道为什么这个表达式不会导致 GHCi 中的堆栈溢出:

foldr (+) 0 [1..5000000] -- 12500002500000

显然,(+) 的两个参数都是严格的,因此必须立即遍历整个列表,懒惰也无济于事。

我的第一个想法是编译器会将(+)识别为关联运算并将其转换为尾递归。

但是,以下操作也有效:

foldr (-) 0 [1..5000000] -- -2500000

这里发生了什么?

GHC 最新的运行时系统让它的堆栈动态增长。尝试限制它,你会看到你的堆栈溢出:

% ghci +RTS -K512K
GHCi, version 8.2.2: http://www.haskell.org/ghc/  :? for help
Prelude> foldr (+) 0 [1..5000000]
*** Exception: stack overflow