這是我在控制檯中看到:
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