2011-02-06 48 views
5

純表達反覆評估我有(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不反覆被分配?

+0

您是否試過編譯指令`{ - #NOINLINE# - }`? – fuz 2011-02-06 12:41:11

回答

4

最簡單的解決方法是通過嚴格的註釋強制評估。

{-# LANGUAGE BangPatterns #-} 

然後通過簡單地使用一個!( 「砰」),使得a嚴格強制分配。

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

另外,如果你是在IO單子工作,嚴格註釋可能並不總是幫助。要運行一些IO行動之前強制進行表達式的計算,可以使用evaluate。例如:

let a = listArray (0, 1000) [x ..] 
    evaluate a 
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)