このコードを最適化する方法に興味があります:
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
これは単に、コンパイラがオーバーライドする定義を提供するためですか?