在IO操作中重复评估纯表达式 [英] Repeated evaluation of pure expression in IO action

查看:176
本文介绍了在IO操作中重复评估纯表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个过程,(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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆