Haskell不支持循环进行计算,而是提供使用递归算法。但是这种方法导致堆栈增加,甚至堆栈溢出。我相信一般应该有办法解决这个问题。这是示例。我想知道,每5秒可以调用getClockTime多少次:
import System.Time
nSeconds = 5
main = do
initTime <- totalPicoSeconds `fmap` getClockTime
doWork initTime 1
where
doWork initTime n = do
currTime <- totalPicoSeconds `fmap` getClockTime
if (currTime - initTime) `div` 10 ^ 12 >= nSeconds
then print n
else doWork initTime (n+1)
totalPicoSeconds :: ClockTime -> Integer
totalPicoSeconds (TOD a b) = a * 10 ^ 12 + b
该程序花了5秒钟,但最终我得到了:
堆栈空间溢出:当前大小为8388608字节。
使用`+ RTS -Ksize -RTS'增加它。
在特定情况下,手动管理堆栈大小可能会有所帮助,但是如果我希望将此算法运行10秒钟,它可能会再次溢出。因此,这不是解决方案。如何使此代码正常工作?
最佳答案
这里的问题不是递归,而是n
参数的惰性。 Haskell中的堆栈溢出来自尝试评估深度嵌套的重击;在您的情况下,每次调用doWork initTime (n+1)
都会在第二个参数中产生一个稍深的嵌套的重击。只需使其严格,事情就应该再次快乐起来:doWork initTime $! n+1
。
关于haskell - 如何避免Haskell中的堆栈溢出?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7534489/