在IO操作中重复评估纯表达式 [英] Repeated evaluation of pure expression in IO action
问题描述
我有一个过程,(a)做一些IO,(b)构造一个查找表,(c)返回一个使用查找表的IO操作。但是当使用 -O
编译时,GHC(6.12.1版本)内置了查找表的构造,因此每次调用IO操作都会重新评估它。
I have a procedure that (a) does some IO, (b) constructs a lookup table, and (c) returns an IO action that uses the lookup table. But when compiled with -O
, GHC (version 6.12.1) inlines the construction the lookup table, so that it is reevaluated for every call of the IO action.
示例:
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-foolproof解决方法 - 或者你如何调整程序,使 a
不是重复分配? p>
Is this issue well-known enough to have a standard GHC-foolproof workaround - or how would you adjust the program so that a
isn't repeatedly being allocated?
推荐答案
最简单的解决方法是使用strictness注释强制评估。
The easiest workaround is to force evaluation by using strictness annotations.
{-# LANGUAGE BangPatterns #-}
然后通过使用!! bang)。
Then force allocation by simply making a
strict using a !
("bang").
let !a = listArray (0, 1000) [x ..]
或者,如果您在 IO
monad中工作,总是帮助。要在运行某些 IO
操作之前强制执行表达式求值,可以使用 evaluate
。例如:
Alternatively, if you are working in the IO
monad, strictness annotations may not always help. To force evaluation of an expression before some IO
action is run, you can use evaluate
. For example:
let a = listArray (0, 1000) [x ..]
evaluate a
这篇关于在IO操作中重复评估纯表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!