正如Why does (sum $ takeWhile (<10000000) [1..]) use so much memory?中提到的,以下不在 ghci 中炸毁内存:
foldl' (+) 0 $ takeWhile (< 10000000) [1 .. ]
但是,如果我创建一个包含以下内容的文件:
import Data.List
longList::[Int]
longList = [1 .. ]
result :: Int
result = foldl' (+) 0 $ takeWhile (< 10000000) longList
main = do
print $ result
并加载到ghci,然后在运行程序时,内存消耗会爆炸。为什么这样,我该怎么做才能解决这个问题呢?我正在使用ghc 7.8.3。
[编辑]
如果先通过ghc Test.hs
编译,不似乎会爆炸。但是,如果我删除所有.hi
和.o
文件,并通过ghci Test.hs
加载到ghci,那么内存会爆炸。
答案 0 :(得分:7)
我认为这是因为当您在GHCi中longList
文件时对标识符:l
的处理方式不同,而不是在编译时。{/ p>
当您在GHCi中:l ModuleName
时,默认情况下模块中的所有顶级标识符都会进入范围,以便您可以有效地进行调试。对于您的示例,这包括longList
。这意味着GHCi 在评估后保留了longList
的内容,这会导致内存泄漏。我怀疑即使使用-fobjectcode
也是如此,所以我不确定其他评论中讨论的行为实际上是一个错误。
当您编译模块时,GHC使用模块导出列表找出结果中公开的标识符。由于您没有明确的module
声明,因此默认为(last paragraph)
module Main (main) where
这意味着在编译时,GHC会注意到除了main
之外的所有标识符都没有公开,longList
只使用一次。然后它可以保持其值,避免内存泄漏。
答案 1 :(得分:2)
请参阅note on GHCI:
部分如果您在GHCi中运行代码时注意到空间泄漏, 请注意,解释的代码与编译的行为不同 代码:即使使用
seq
。考虑按如下方式启动ghci:
$ ghci -fobject-code