【发布时间】:2010-05-19 21:57:37
【问题描述】:
我想知道为什么
Prelude> head $ reverse $ [1..10000000] ++ [99]
99
不会导致堆栈溢出错误。前奏中的 ++ 似乎是直截了当且非尾递归的:
(++) :: [a] -> [a] -> [a]
(++) [] ys = ys
(++) (x:xs) ys = x : xs ++ ys
编辑:最初,我认为这个问题与前奏中定义 ++ 的方式有关,特别是与重写规则有关,因此问题继续如下。讨论告诉我,事实并非如此。我现在认为某些惰性求值效果会导致代码在没有堆栈溢出的情况下运行,但我不太清楚如何。
所以就这样,它应该会遇到堆栈溢出,对吗?所以我认为这可能与遵循 ++ 定义的 ghc 魔法有关:
{-# 规则 "++" [~1] 对于所有 xs ys。 xs ++ ys = 增加 (\c n -> foldr c n xs) ys #-}
*这有助于避免堆栈溢出吗?有人可以为这段代码中发生的事情提供一些提示吗?**
【问题讨论】:
-
重写规则不会在解释器中触发(除非您启用它们)。
-
@Don:谢谢,我没有启用它们。无论如何,我应该在输入之前检查一下:A new function "f s t = if s == [] then t else let (x:ss) = s in x:(f ss t)" 也不会导致堆栈溢出,因此它与规则部分没有任何关系......
标签: haskell lazy-evaluation ghc tail-recursion