並列プログラミングとその後の評価戦略を検討しているときに、サンクが可変であるかどうかという疑問が浮かびました。例を挙げると、次のコードがあるとします。
foo = 1 + 2 -- Thunk
bar = foo `seq` foo -- Evaluates foo
評価seq
時に呼び出すと、が評価され、正規形の値が得られます。この評価も影響しますか?つまり、の値はまだですか、それとも評価後ですか?bar
foo
bar
3
foo
foo
1+2
3
bar
並列プログラミングとその後の評価戦略を検討しているときに、サンクが可変であるかどうかという疑問が浮かびました。例を挙げると、次のコードがあるとします。
foo = 1 + 2 -- Thunk
bar = foo `seq` foo -- Evaluates foo
評価seq
時に呼び出すと、が評価され、正規形の値が得られます。この評価も影響しますか?つまり、の値はまだですか、それとも評価後ですか?bar
foo
bar
3
foo
foo
1+2
3
bar
Haskellレポートは、評価順序が「非厳密」であると指定しているだけなので、どちらの動作も標準に準拠します。
ただし、怠惰な(「必要に応じて呼び出す」)評価を使用すると、説明するようにサンクを「可変」にする方法で値を共有することが含まれ、「名前による呼び出し」(つまり、共有なし)よりも漸近的に改善されます。
したがって、GHC(およびおそらく他のほとんどの合理的な実装)では、初めて強制した後にfoo
なります。3
ただし、これは標準では義務付けられていないため、注意する必要があります。
foo
とbar
はConstant Applicative Formsであり、(リンクから引用):
...すべての用途で共有されるグラフの一部にコンパイルするか、最初に評価されるときにグラフでそれ自体を上書きする共有コードにコンパイルできます。
この文の 2 番目の部分は遅延評価に対応し、foo
評価後は 3 になりますbar
。最初の部分はより一般的です (グラフの共有部分に何が起こるかは述べていません) foo
。