(a)IOをいくつか行い、(b)ルックアップテーブルを構築し、(c)ルックアップテーブルを使用するIOアクションを返します。しかし、-O
でコンパイルすると、GHC(バージョン6.12.1)は構造をルックアップテーブルにインライン化するので、IOアクションの呼び出しごとに再評価されます。IOアクションでの純粋な表現の繰り返し評価
例:
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
この問題は、標準のGHC-確実な回避策を持っているために十分によく知られている - または繰り返し割り当てられていませんa
ようにどのようにプログラムを調整するのでしょうか?返すようにモナド値を構築する際に
プラグマ '{ - #NOINLINE# - }'を試しましたか? – fuz
@FUZxxlはい、 '{ - #NOINLINE a# - }'はローカルの 'a'でそれをしません。 – antonakos
ルックアップテーブルを必要とし、繰り返しアクション間で共有したい場合は、必ず@ makeAction @関数から作成する必要があります。 makeActionはインライン展開に関係なく毎回配列を作成するようです。おそらく、あなたはmakeAction関数から引き上げられたIOArrayを使うべきです。 –