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/

10-11 02:35