2011-09-23 14 views
14

Haskell no es compatible con el ciclo para el cálculo, sino que ofrece el uso de algoritmos de recursión. Pero este enfoque conduce al crecimiento de la pila, e incluso al desbordamiento de la pila. Creo que debería haber un enfoque para resolver este problema en general. Aquí está la muestra. Lo que quería saber, ¿cuántas veces getClockTime pueden ser llamados por cada 5 segundos:¿Cómo evitar el desbordamiento de pila en Haskell?

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 

El programa va más de 5 segundos, pero con el tiempo me estoy haciendo:

Pila espacio de desbordamiento: tamaño actual 8388608 bytes.
Use `+ RTS -Ksize -RTS 'para aumentarlo.

La gestión manual del tamaño de pila puede ayudar en un caso particular, pero si quisiera ejecutar este algo durante 10 segundos, podría desbordarse de nuevo. Entonces esta no es una solución. ¿Cómo puedo hacer que este código funcione?

+2

¿No es esta cola recursiva? ¿Por qué está creciendo la pila? – Swiss

+0

¿Compiló con o sin optimizaciones? – fuz

+6

@Swiss Sí, es recursivo en la cola, pero la pila que está creciendo no es la pila que crees que está creciendo. –

Respuesta

27

El problema aquí no es la recursividad, sino la pereza de su argumento n. Los desbordamientos de pila en Haskell provienen de tratar de evaluar los troncos profundamente anidados; en su caso, cada llamada a doWork initTime (n+1) está haciendo un procesador anidado ligeramente más profundo en el segundo argumento. Simplemente hágalo estricto, y las cosas deberían ser felices de nuevo: doWork initTime $! n+1.

+0

Funciona. ¡Estupendo! –

+0

¡Muy buena captura! – acfoltzer

+1

P.S. El crédito aquí va para Brent Yorgey, quien me ayudó a depurar un error casi idéntico en algunos de mis códigos hace casi tres años. –

Cuestiones relacionadas