我對 Haskell 比較陌生,而且總體上對編程缺乏經驗。一個函式在某些輸入上導致堆疊溢位,我不知道為什么。
有問題的功能:
digitSum :: Integer -> Integer -> Integer
digitSum _ 1 = 1
digitSum base x = (x `mod` base) digitSum base (x `div`base)
在某些輸入(例如 10 15、11 121、16 19、3 1234)上它可以作業,而在其他輸入(例如 10 456)上它會中斷 有人可以向我解釋一下,以便我以后可以避免它嗎?
uj5u.com熱心網友回復:
函式式語言中的堆疊溢位通常意味著:無限遞回。而且,事實上,對于很多輸入,這就是這里發生的情況:例如digitSum 2 0. 它與第一個模式匹配不匹配,因此它適用于第二種情況,使用base=2and x=0。x `mod` base = 1和x `div` base = 0。然后它遞回呼叫digitSum 2 0. 然后永遠。
這是因為您的基本情況是錯誤的:應該是digitSum _ 0 = 0,因為如果您保持整數除以x,base如果base不是1,您將始終以0.
uj5u.com熱心網友回復:
BlackBeans 有正確的答案,但作為附錄,不僅在無限遞回中,而且在遞回過多時,都可能看到堆疊溢位。幸運的是,這很容易通過以尾遞回方式撰寫函式來解決。如果你這樣做,你的 Haskell 編譯器可以在常量堆疊空間中運行函式。
實作這一點的常用方法是添加一個累加器引數,這通常對使用本地函式的函式用戶隱藏。
digitSum :: Integer -> Integer -> Integer
digitSum = digitSum' 0
where
digitSum' acc _ 0 = acc
digitSum' acc base x = digitSum (acc x `mod` base) base (x `div` base)
如果您以尾遞回樣式撰寫函式并且具有無限遞回,則不要期望看到堆疊溢位,但確實希望看到程式只是掛起,因為遞回沒有終止。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/528534.html
標籤:哈斯克尔堆栈溢出
上一篇:Haskell如何將元組串列中元組的第二個元素加在一起
下一篇:將受約束的文字分配給多型變數
