2013-01-12 10 views
9

これは私がコンソールに得るものです:2GB上だ

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

!私はsumがすでに合計しているものを捨てることができると思います。どうやってこれを書くのですか?

答えて

12

あなたは千万Integer Sを作成し、リストの細胞がたくさんいます。また、コンパイラで実行した場合は、解釈されたコードを実行しているため、割り当てがやや減ります。

主な問題は、インタープリタがまったく最適化しないため、sumは、巨大なサンクを構築する遅延型バリアントを使用することです。 sumはそれだけで罰金消費したリストの一部を破棄し、それはそう

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は正常に動作します。

5

これはまさにだからここソリューションは、(import Data.Listを必要とする)foldl' (+) 0 $ takeWhile (<10000000) [1..]可能性がありhttp://www.haskell.org/haskellwiki/Memory_leak

で説明しているもののように見えます。

私はちょうどハスケル初心者で好奇心が強いので、おそらくもっと良い解決策があります。 =^^ = (編集: :-P下の最初のコメントを読んでください)。

+7

"GHCiでコードを実行しているときにスペースリークが発生した場合、解釈されたコードは' seq'を使用していてもコンパイルされたコードとは異なる動作をすることに注意してください。 - http://www.haskell.org/haskellwiki/Memory_leak – cacba

関連する問題