このコードを最適化する方法に興味があります:
fun n = (sum l, f $ f0 l, g $ g0 l)
where l = map h [1..n]
f、f0、g、g0、およびhはすべてコストがかかると仮定しますが、 の作成と保存にlは非常にコストがかかります。
書かれているようにl、返されたタプルが完全に評価されるかガベージ コレクションされるまで格納されます。代わりに、length l、f0 l、およびg0 lのいずれかが実行されるたびにすべて実行する必要がfありますが、 およびgは遅延させる必要があります。
この動作は、次のように書くことで修正できるようです:
fun n = a `seq` b `seq` c `seq` (a, f b, g c)
where
l = map h [1..n]
a = sum l
b = inline f0 $ l
c = inline g0 $ l
または非常に似ています:
fun n = (a,b,c) `deepSeq` (a, f b, g c)
where ...
同じ効果を実現するために内部型の束を指定することもできますが、これは面倒に見えます。他のオプションはありますか?
inlineまた、コンパイラsumが 、f0、およびを融合して、項g0ごとに構築および消費する単一のループにすることを明らかに望んでいます。l手動でインライン化することでこれを明示的にすることもできますが、それは最悪です。リストが作成されないように明示的に防止したり、lインライン化を強制したりする方法はありますか? コンパイル中にインライン化または融合が失敗した場合に警告またはエラーを生成するプラグマはおそらく?
余談ですが、プレリュードで 、 、 などがすべて by にseq定義inlineさlazyれている理由が気になります。let x = x in xこれは単に、コンパイラがオーバーライドする定義を提供するためですか?