这是我在控制台中看到:
ghci> sum $ takeWhile (<10000000) [1..]
49999995000000
(11.96 secs, 2174569400 bytes)
这是超过2GB!我会想象sum
可以放弃它已经总结的任何东西。你会如何写这个?
这是我在控制台中看到:
ghci> sum $ takeWhile (<10000000) [1..]
49999995000000
(11.96 secs, 2174569400 bytes)
这是超过2GB!我会想象sum
可以放弃它已经总结的任何东西。你会如何写这个?
你创造千万Integer
S,和大量的名单细胞。另外,如果你运行的是解释代码,那么你就可以通过编译器运行它,这会减少分配。
主要的问题是解释器根本没有进行优化,所以sum
使用了构建thunk的懒惰变体。列表中的sum
丢弃部分它已经消耗得很好,但它有一个thunk计算结果后来取代它,所以
sum [1,2,3,4 ...]
成为
(...((((0 + 1) + 2) + 3) + 4) + ...)
之后。这不是最佳的替代品,因为Integer
s的加入是严格的。
在ghci的提示,你应该写
Prelude Data.List> foldl' (+) 0 $ takeWhile (< 10000000) [1 .. ]
49999995000000
(1.41 secs, 1443355832 bytes)
来解决这个问题。在编译(当然有优化)程序中,sum
将正常工作。
这看起来很像是怎么在http://www.haskell.org/haskellwiki/Memory_leak
描述所以这里的解决方案可能是foldl' (+) 0 $ takeWhile (<10000000) [1..]
(这需要import Data.List
)。
可能有更好的解决方案,因为我只是一个Haskell新手而且也很好奇。 =^^ = 。(编辑:请阅读以下:-P第一评论)
“如果您在GHCi中运行您的代码时发现空间泄露,请注意解释的代码与编译代码的行为不同:即使使用seq'。” - http://www.haskell.org/haskellwiki/Memory_leak – cacba