5

(a) IO を実行し、(b) ルックアップ テーブルを作成し、(c) ルックアップ テーブルを使用する IO アクションを返すプロシージャがあります。しかし、 でコンパイルすると-O、GHC (バージョン 6.12.1) はルックアップ テーブルの構築をインライン化し、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繰り返し割り当てられないようにプログラムをどのように調整しますか?

4

2 に答える 2

4

最も簡単な回避策は、厳密性の注釈を使用して評価を強制することです。

{-# LANGUAGE BangPatterns #-}

次に、 ( "bang")aを使用して厳密にするだけで、割り当てを強制します。!

    let !a = listArray (0, 1000) [x ..]

IOまたは、モナドで作業している場合、厳密性の注釈が常に役立つとは限りません。アクションを実行する前に式の評価を強制するにはIO、を使用できますevaluate。例えば:

    let a = listArray (0, 1000) [x ..]
    evaluate a
于 2011-02-06T13:23:45.973 に答える
2

aモナディック値を作成するときに強制的に返すようにしてください。

makeAction getX getY sumRef = do
    x <- getX
    let a = listArray (0, 1000) [x ..]
    return $ a `seq` do
        y <- getY
        modifyIORef sumRef (\sum -> sum + a ! y)
于 2011-02-06T13:23:36.373 に答える