簡體   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