10

これは私がコンソールに表示するものです:

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

それは2GBを超えています!sum私はそれがすでに合計したものは何でも捨てることができると想像します。これをどのように書きますか?

4

2 に答える 2

13

あなたは1000万Integer秒とたくさんのリストセルを作成しています。また、インタープリターされたコードを実行している場合、コンパイラーを介して実行すると、割り当てがいくらか減少します。

主な問題は、インタプリタがまったく最適化されていないことです。そのため、は巨大なサンクsumを構築する怠惰なバリアントを使用します。正常に消費したリストの一部を破棄しますが、後で結果を計算するためにサンクに置き換えます。sum

sum [1,2,3,4 ...]

になります

(...((((0 + 1) + 2) + 3) + 4) + ...)

その後。Integersの追加は厳密であるため、これは最適な置換ではありません。

ghciプロンプトで、次のように書く必要があります

Prelude Data.List> foldl' (+) 0 $ takeWhile (< 10000000) [1 .. ]
49999995000000
(1.41 secs, 1443355832 bytes)

それを修正します。コンパイルされた(もちろん最適化された)プログラムでは、sum正常に機能します。

于 2013-01-12T23:25:50.857 に答える
6

これは、 http://www.haskell.org/haskellwiki/Memory_leakで説明されているものとまったく同じように見えます

したがって、ここでの解決策はfoldl' (+) 0 $ takeWhile (<10000000) [1..](必要なimport Data.List)である可能性があります。

私はHaskellの初心者であり、好奇心旺盛だったので、おそらくもっと良い解決策があります。=^。^=(編集:以下の最初のコメントを読んでください:-P)

于 2013-01-12T23:25:03.290 に答える