Tengo un procedimiento que (a) hace algunos IO, (b) construye una tabla de búsqueda y (c) devuelve una acción IO que usa la tabla de búsqueda. Pero cuando se compila con -O
, GHC (versión 6.12.1) detalla la construcción de la tabla de búsqueda, de modo que se reevalúa para cada llamada de la acción IO.Evaluación repetida de la expresión pura en la acción IO
Ejemplo:
module Main where
import Data.Array
import Data.IORef
import Control.Monad
makeAction getX getY sumRef = do
x <- getX
let a = listArray (0, 1000) [x ..]
return $ do
y <- getY
modifyIORef sumRef (\sum -> sum + a ! y)
main = do
sumRef <- newIORef 0
action <- makeAction getX getY sumRef
replicateM_ 100000 action
n <- readIORef sumRef
putStrLn (show n)
where
getX = return (1 :: Int)
getY = return 0
¿Es este problema bien conocido lo suficiente como para tener una solución GHC-toda prueba estándar - o cómo habría que ajustar el programa para que a
en repetidas ocasiones no está siendo asignado?
¿Has probado el pragma '{- # NOINLINE # -}'? – fuz
@FUZxxl Sí, '{- # NOINLINE a # -}' en el 'a' local no lo hace. – antonakos
Si quiere una tabla de búsqueda y desea compartirla entre las acciones repetidas, seguramente debería separarla de la función @ makeAction @? Parece que makeAction hará una matriz cada vez independientemente de la alineación. Tal vez deberías estar usando un IOArray extraído de la función makeAction. –