で部分的に計算を最適化:私はこのコードを最適化する方法を興味ハスケル
そのf
、
f0
、
g
、
g0
、および
h
は全て高価であるが、
l
の作成と保存が非常にあると仮定すると
fun n = (sum l, f $ f0 l, g $ g0 l)
where l = map h [1..n]
高価な。
返されたタプルが完全に評価されるかガベージコレクションされるまで、l
が格納されます。代わりに、length l
,f0 l
、およびg0 l
は、いずれか1つを実行するときにすべて実行する必要がありますが、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 ...
我々は、おそらく同様に同様の効果を得るために、内部のタイプの束を指定することができ、痛いようです。他のオプションはありますか?また
、私は明らかにコンパイラが作成し、用語によってl
用語を消費し、単一のループにsum
、f0
、およびg0
を融合することを私inline
Sと願っています。手動のインライン展開でこれを明示的にすることもできますが、それはうまくいくでしょう。リストl
が明示的に作成されないようにする方法やインライン展開を強制する方法はありますか?おそらく、コンパイル時にインライン展開やフュージョンが失敗した場合に警告やエラーを生成するプラグマ?余談として
は、私はすべてのプレリュードでlet x = x in x
によって定義されている理由seq
、inline
、lazy
などについて興味があります。これは単純にコンパイラがオーバーライドするための定義を与えることですか?
最後の質問への回答:http://stackoverflow.com/a/8654407/1011995 –
'f0'と' g0'は完全に任意であるか、 'foldr'の形で書くことができますか? – dave4420
(a、b、c) - アキュムレータで簡単に折り畳むことはできませんか? – Sarah