2011-02-06 20 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)