Haskell での遅延評価に関する私の苦労の 1 つは、メモリ使用量についての推論の難しさです。サンクを複製する機能があれば、これがずっと簡単になると思います。例を次に示します。
本当に大きなリストを作成しましょう:
let xs = [1..10000000]
それでは、悪い関数を作成しましょう。
bad = do
print $ foldl1' (+) xs
print $ length xs
最適化を行わないと、数十 MB の RAM が消費されます。後で長さを計算するために必要になるため、ガベージ コレクターは折りたたみ中に xs の割り当てを解除できません。
この関数を次のように再実装することは可能ですか:
good = do
(xs1,xs2) <- copyThunk xs
print $ foldl1' (+) xs1
print $ length xs2
ここで、xs1 と xs2 は同じ値を表しますが、メモリ内で互いに独立しているため、フォールド中にガベージ コレクタが割り当てを解除でき、メモリの浪費を防ぐことができます。(計算コストが若干上がると思いますが?)
この些細な例では明らかに、コードをリファクタリングすることでこの問題を簡単に解決できますが、リファクタリングの方法が常に明らかであるとは限りません。または、リファクタリングによってコードの明瞭さが大幅に低下する場合もあります。