2013-01-12 31 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

相關問題