¿Cómo forzar la evaluación en Haskell?
lazy-evaluation (2)
Usaría la extensión de lenguaje -XBangPatterns , me parece bastante expresivo en tales situaciones. Entonces, tendría que decir " let !r = foo inputList
" como en:
{-# LANGUAGE BangPatterns #-}
import System.CPUTime
benchmark :: [String] -> IO Integer
benchmark inputList = do
start <- getCPUTime
let !r = foo inputList
end <- getCPUTime
return (end - start)
Soy relativamente nuevo en Haskell y estoy tratando de aprender cómo se pueden ejecutar diferentes acciones en secuencia usando la notación do. En particular, estoy escribiendo un programa para comparar un algoritmo (una función)
foo :: [String] -> [String]
Para este propósito, me gustaría escribir una función como
import System.CPUTime
benchmark :: [String] -> IO Integer
benchmark inputList = do
start <- getCPUTime
let r = foo inputList
end <- getCPUTime
return (end - start) -- Possible conversion needed.
La última línea puede necesitar una conversión (por ejemplo, a milisegundos) pero este no es el tema de esta pregunta.
¿Es esta la forma correcta de medir el tiempo necesario para calcular la función foo en algún argumento inputList?
En otras palabras, ¿la expresión foo inputList
se reducirá completamente antes de que se ejecute la acción end <- getCPUTime
? ¿O solo estará ligado al thunk foo inputList
?
Más en general, ¿cómo puedo garantizar que una expresión se evalúe por completo antes de que se ejecute alguna acción?
Esta pregunta fue hecha hace unos meses sobre los programadores (ver aquí ) y tuvo una respuesta aceptada allí, pero se ha cerrado como fuera de tema porque pertenece al desbordamiento de la pila. La pregunta no se pudo mover al desbordamiento de la pila porque es anterior a 60 días. Entonces, de acuerdo con los moderadores, vuelvo a enviar la pregunta aquí y publico la pregunta aceptada porque creo que contiene información útil.
Respuesta originalmente dada por el usuario ysdx a los programadores :
De hecho, su versión no comparará su algoritmo. Como
r
no se usa, no se evaluará en absoluto.Deberías poder hacerlo con DeepSeq :
benchmark :: [String] -> IO Integer benchmark inputList = do start <- getCPUTime let r = foo inputList end <- r `deepseq` getCPUTime return (end - start)
(
a `deepseq` b
) es una expresión" mágica "que fuerza la evaluación completa / recursiva dea
antes de regresarb
.