这是我在控制台中获得的内容:
ghci> sum $ takeWhile (<10000000) [1..]
49999995000000
(11.96 secs, 2174569400 bytes)
超过2GB!我想,sum
可以丢弃它已经总结的任何东西。你会怎么写这个?
答案 0 :(得分:12)
你创造了一千万Integer
个,以及很多列表单元格。此外,如果您通过编译器运行解释代码,则会运行解释代码,这会在一定程度上减少分配。
主要问题是解释器根本没有优化,因此sum
使用构建巨大 thunk的惰性变体。 sum
丢弃它已经消耗的列表部分,但它会用thunk替换它来计算结果,所以
sum [1,2,3,4 ...]
变为
(...((((0 + 1) + 2) + 3) + 4) + ...)
之后。这不是最佳替代,因为Integer
的加法是严格的。
在ghci提示符下,您应该写
Prelude Data.List> foldl' (+) 0 $ takeWhile (< 10000000) [1 .. ]
49999995000000
(1.41 secs, 1443355832 bytes)
解决这个问题。在编译(当然还有优化)程序中,sum
可以正常工作。
答案 1 :(得分:5)
这看起来与http://www.haskell.org/haskellwiki/Memory_leak
中描述的完全相同因此,此处的解决方案可能是foldl' (+) 0 $ takeWhile (<10000000) [1..]
(需要import Data.List
)。
可能有一个更好的解决方案,因为我只是一个Haskell新手并且也很好奇。 = ^。^ = (编辑:请阅读以下第一条评论:-P)