2013-01-12 30 views
9

这是我在控制台中看到:

ghci> sum $ takeWhile (<10000000) [1..] 
49999995000000 
(11.96 secs, 2174569400 bytes) 

这是超过2GB!我会想象sum可以放弃它已经总结的任何东西。你会如何写这个?

回答

12

你创造千万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将正常工作。

5

这看起来很像是怎么在http://www.haskell.org/haskellwiki/Memory_leak

描述所以这里的解决方案可能是foldl' (+) 0 $ takeWhile (<10000000) [1..](这需要import Data.List)。

可能有更好的解决方案,因为我只是一个Haskell新手而且也很好奇。 =^^ = 。(编辑:请阅读以下:-P第一评论)

+7

“如果您在GHCi中运行您的代码时发现空间泄露,请注意解释的代码与编译代码的行为不同:即使使用seq'。” - http://www.haskell.org/haskellwiki/Memory_leak – cacba

相关问题