Mam procedurę, która (a) wykonuje niektóre operacje wejścia/wyjścia, (b) tworzy tabelę odnośników, i (c) zwraca operację we/wy, która używa tabeli odnośników. Jednak po skompilowaniu z -O
, GHC (wersja 6.12.1) naświetla konstrukcję tabeli odnośników, dzięki czemu jest ona ponownie oceniana dla każdego wywołania działania IO.Powtórna ocena czystego wyrażenia w akcji IO
Przykład:
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
Jest to problem znany wystarczy mieć standardową GHC-niezawodny obejście - albo jak można ustawić program tak, że a
nie jest wielokrotnie są rozdzielone?
Czy próbowałeś pragma '{- # NOINLINE # -}'? – fuz
@FUZxxl Tak, '{- # NOINLINE a # -}' na lokalnym 'a' nie robi tego. – antonakos
Jeśli chcesz tabeli odnośników i chcesz podzielić się nią z powtarzającymi się czynnościami, z pewnością należy oddzielić tworzenie go od funkcji @ makeAction @? Wygląda na to, że makeAction będzie tworzyć tablicę za każdym razem, niezależnie od inliningu. Może powinieneś używać IOArray wyciągniętej z funkcji makeAction. –