繁体   English   中英

每个Haskell函数都执行尾调用吗?

[英]Does every Haskell function do tail calls?

我想知道Haskell中的每个函数都应该是尾递归的。

阶乘函数实现为非尾递归函数:

fact 0 = 1
fact n = n * fact (n - 1)

每个运算符也是一个函数,所以这等效于

fact 0 = 1
fact n = (*) n (fact (n - 1))

但这显然是我的尾声。 我想知道如果每个调用都只是在堆上创建一个新的thunk,那么这段代码为什么会导致堆栈溢出。 我不应该堆溢出吗?

在代码中

fact 0 = 1
fact n = (*) n (fact (n - 1))

如您所见,最后一个(*) ...是尾部调用。 但是,最后一个实参fact (n-1)将产生一个thunk,紧接着(*)要求它。 这导致对fact的无尾的呼吁。 递归地,这将消耗堆栈。

TL; DR:发布的代码执行尾部调用,但(*)则不执行。

(此外,Haskell中的“堆栈”概念并不像严格的语言中那么清晰。Haskell的某些实现使用的东西要比这复杂得多。如果需要一些详细信息,可以搜索“推入/输入vs评估/应用”策略。 。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM