12

この関数を考えてみましょう:

f as = if length as > 100 then length as else 100

関数は純粋なので、両方の呼び出しで長さが同じになることは明らかです。私の質問は、Haskell オプティマイザーが上記のコードを以下と同等のものに変換するかどうかです。

f as = 
  let l = length as
  in if l > 100 then l else 100

もしそうなら、どのレベル設定がそれを可能にしますか? そうでない場合、なぜですか?このシナリオでは、関数の実行が終了するとすぐに導入された変数が解放されるため、この回答で説明されているように、メモリの浪費が理由になることはありません。


ローカルスコープのため、これはこの質問の複製ではないことに注意してください。したがって、根本的に異なる回答が得られる可能性があります。

4

3 に答える 3

16

フラグがオンになっているため、GHCはデフォルトでCSEを実行するようになりました。-fcse

デフォルトでオン..共通部分式除去の最適化を有効にします。これをオフに切り替えると、一般化したくない安全でないPerformIO式がある場合に役立ちます。

ただし、共有の導入に問題があるため(したがってスペースリーク)、保守的です。ただし、CSEパスは少し良くなっています(そしてこれ)。

最後に、完全なCSE用のプラグインがあることに注意してください。

あなたがそれから利益を得ることができるコードを持っているなら。

于 2013-02-26T09:16:53.023 に答える
13

このようなローカル設定でも、共有の導入が常に最適化であるかどうかは明らかではありません。この定義例を検討してください

f = if length [1 .. 1000000] > 0 then head [1 .. 1000000] else 0

対これ

f = let xs = [1 .. 1000000] in if length xs > 0 then head xs else 0

この場合、リストで実行される各計算が安価であるため、最初のバージョンの動作がはるかに優れているのに対し、2番目のバージョンでは、リストがメモリ内で完全に展開されlength、破棄することしかできません。head削減された後。

于 2013-02-26T08:13:35.640 に答える
5

あなたが説明しているケースは、メモ化よりも一般的な部分式の削除に関係していますが、意図しない共有がスペースリークにつながる可能性があるため、 GHC は現在それを行っていないようです。

于 2013-02-26T08:57:36.843 に答える