非尾递归函数在GHCi中没有爆炸。为什么?

时间:2013-12-01 14:05:52

标签: haskell functional-programming tail-recursion ghci

我期待看到我的堆栈与下面的代码打击..但它没有:

*Main> let blowwss x = if x == 0 then 0 else (1 + blowwss (x-1))
*Main> blowwss 1000000
1000000

这个功能似乎不是尾递归的,所以我想知道我可能缺少什么。 GHCi的堆栈是否比我想象的要大(我怎么能看到它的堆栈大小,顺便说一下?)。它是否使用某种蹦床来克服这个问题?是否足够智能将函数转换为迭代对应物?

由于

2 个答案:

答案 0 :(得分:8)

GHCi的筹码比你想象的要大。 IIRC,GHCi的默认堆栈大小为500M,而编译程序的默认堆栈大小目前为8M。您可以自己设置一个较小的限制,以查看堆栈溢出(或者您可以显着增加您的参数)。

$ ghci +RTS -K1M
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> let blowwss x = if x == 0 then 0 else (1 + blowwss (x-1))
Prelude> blowwss 1000000
*** Exception: stack overflow

请注意,GHC的堆栈大小限制纯粹是为了防止在最可能出现编程错误的情况下出现无限/意外深度循环。原则上,堆栈可以无限增长(当然,受系统内存约束)。即使您指定了较大的堆栈大小,堆栈实际上也会开始变小,但可以增长到极限。目前有关于在未来版本的GHC中可能完全取消限制的讨论。

答案 1 :(得分:1)

您使用的值太小了。我已将您的功能移到单独的文件

blowwss x = if x == 0 then 0 else (1 + blowwss (x-1))

main = do
  print $ blowwss 10000000000
  print $ blowwss 10000000000000

然后编译并运行

[mihai@esgaroth tmp]$ ghc --make 1.hs
[1 of 1] Compiling Main             ( 1.hs, 1.o )
Linking 1 ...
[mihai@esgaroth tmp]$ ./1
Stack space overflow: current size 8388608 bytes.
Use `+RTS -Ksize -RTS' to increase it.

在GHCI中运行我得到高负载然后堆栈溢出。那是因为GHCi的堆栈更高,我估计大约512M。