3

厳密さについていくつか質問してきましたが、以前は的を射ていなかったと思います。うまくいけば、これはより正確です。

私たちが持っているとしましょう:

n = 1000000
f z = foldl' (\(x1, x2) y -> (x1 + y, y - x2)) z [1..n]

を変更せずにf、何を設定すればよいですか

z = ...

それf zはスタックをオーバーフローしませんか?(つまり、n のサイズに関係なく、一定の空間で実行されます)

答えが GHC 拡張機能を必要とする場合は問題ありません。


私の最初の考えは、次のように定義することです。

g (a1, a2) = (!a1, !a2)

その後

z = g (0, 0)

gしかし、有効な Haskell だとは思いません。

4

2 に答える 2

9

したがって、strictfoldl'は、折り畳みの各ステップでラムダの結果をWeak Head Normal Formに評価するだけです。つまり、最も外側のコンストラクタでのみ strict になります。したがって、タプルは評価されますが、タプルのこれらの追加はサンクとして蓄積される可能性があります。この詳細な回答は、実際にここでの正確な状況に対処しているようです。

W/R/T your g: 次のBangPatternsような拡張機能を考えています。

g (!a1, !a2) = (a1, a2)

タプルで返す前に a1 と a2 を WHNF に評価します。

気にしたいのは、最初のアキュムレータではなく、ラムダ式です。これは素晴らしい解決策です:

f z = foldl' (\(!x1, !x2) y -> (x1 + y, y - x2)) z [1..n]

編集:あなたの他の質問に気づいた後、私はこれを注意深く読んでいなかったことがわかりました. あなたの目標は、いわば「厳密なデータ」を持つことです。他のオプションは、フィールドに厳密性タグを持つ新しいタプル型を作成することです。

data Tuple a b = Tuple !a !b

次に、 でパターン マッチを行うとTuple a babが評価されます。

関係なく、関数を変更する必要があります。

于 2012-06-20T03:12:23.707 に答える
3

変更せずにできることは何もありませんf。ペアのタイプがオーバーロードされている場合fは、厳密なペアを使用できますが、現状では、何をするかに縛られてfいます。コンパイラ (厳密性分析と変換) がスタックの増加を回避できるというわずかな希望がありますが、期待できるものは何もありません。

于 2012-06-20T08:52:58.930 に答える