1. ホーム
  2. haskell

[解決済み] Haskellはガベージコレクタを必要としますか?

2022-08-14 18:43:02

質問

Haskellの実装がなぜGCを使用するのか、興味があります。

純粋な言語においてGCが必要なケースは思いつきません。単にコピーを減らすための最適化なのか、それとも実際に必要なのか?

GCがなかったらリークするようなコードの例を探しています。

どのように解決するのですか?

既に他の方が指摘されているように、Haskellでは 自動 , 動的 メモリ管理:手動でのメモリ管理は安全でないため、自動的なメモリ管理が必要です。プログラムによっては、オブジェクトの寿命は実行時にしか決定できないため、動的なメモリ管理が必要です。

例えば、次のようなプログラムを考えてみましょう。

main = loop (Just [1..1000]) where
  loop :: Maybe [Int] -> IO ()
  loop obj = do
    print obj
    resp <- getLine
    if resp == "clear"
     then loop Nothing
     else loop obj

このプログラムでは、リスト [1..1000] はユーザが "clear" をタイプするまでメモリ内に保持されなければならないので、この は動的に決定されるため、動的なメモリ管理が必要です。

この意味で、自動的な動的メモリ割り当てが必要なわけですが、実際のところこれは はい

ガベージコレクションは最も高性能な自動動的メモリマネージャであるため、Haskell はガベージコレクタを必要とします。

しかしながら...

ガベージコレクタは必要ですが、コンパイラがガベージコレクションより安いメモリ管理スキームを使用できるいくつかの特別なケースを見つけようとするかもしれません。例えば、与えられた

f :: Integer -> Integer
f x = let x2 = x*x in x2*x2

を検出するようなコンパイラを望むかもしれません。 x2 が安全に解放されることを f が戻ったときに安全に割り当て解除されます (ガベージコレクタが x2 ). 基本的に、私たちはコンパイラに次のことを要求しています。 エスケープ解析 を実行して、ガベージコレクションのヒープへのアロケーションを スタック上のアロケーション に変換します。

これはあまり無理な要求ではありません。 jhc ハスケルコンパイラ はこれを行いますが、GHC はこれを行いません。Simon Marlow は言います。 は、GHCの世代別ガベージコレクタがエスケープ解析をほとんど不要にしていると言っています。

jhc は実際には、エスケープ解析の洗練された形式である 領域推論 . を考慮します。

f :: Integer -> (Integer, Integer)
f x = let x2 = x * x in (x2, x2+1)

g :: Integer -> Integer
g x = case f x of (y, z) -> y + z

この場合、単純化されたエスケープ分析では、次のように結論づけられます。 x2 から脱出する。 f (をエスケープし(タプルの中で返されるため)、その結果 x2 はガベージコレクションされたヒープ上に割り当てられなければならない。一方、領域推論では x2 が割り当て解除されたときに g が戻ったときに解放されます。 x2 に割り当てるべきということです。 g の領域ではなく f

f :: Integer -> Integer f n = product [1..n]