Tôi có một quy trình (a) thực hiện một số IO, (b) xây dựng bảng tra cứu và (c) trả về hành động IO sử dụng bảng tra cứu. Nhưng khi biên dịch với -O
, GHC (phiên bản 6.12.1) inlines xây dựng bảng tra cứu, để nó được đánh giá lại cho mọi cuộc gọi của hành động IO.Lặp lại đánh giá biểu thức thuần túy trong hành động IO
Ví dụ:
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
là vấn đề này nổi tiếng đủ để có một workaround GHC-cao độ tiêu chuẩn - hoặc làm thế nào bạn sẽ điều chỉnh chương trình để a
không liên tục được phân bổ?
Bạn đã thử pragma '{- # NOINLINE # -}'? – fuz
@FUZxxl Có, '{- # NOINLINE a # -}' trên địa phương 'a' không làm điều đó. – antonakos
Nếu bạn muốn một bảng tra cứu và muốn chia sẻ nó giữa các hành động lặp lại, chắc chắn bạn nên tách riêng nó ra khỏi hàm @ makeAction @? Dường như makeAction sẽ tạo một mảng mỗi lần bất kể nội tuyến. Có lẽ bạn nên sử dụng một IOArray treo ra khỏi hàm makeAction. –