Як уже вказували інші, 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]
повинен зберігатися в пам'яті до тих пір, поки користувач не набере "очистити"; тому час життя цього повинен визначатися динамічно, і саме тому необхідне динамічне управління пам’яттю.
Тож у цьому сенсі необхідний автоматизований динамічний розподіл пам’яті, а на практиці це означає: так , Haskell вимагає сміттєзбірника, оскільки збирання сміття є найвищою ефективністю автоматичного динамічного диспетчера пам’яті.
Однак ...
Хоча сміттєзбірник необхідний, ми можемо спробувати знайти деякі особливі випадки, коли компілятор може використовувати більш дешеву схему управління пам'яттю, ніж збирання сміття. Наприклад, дано
f :: Integer -> Integer
f x = let x2 = x*x in x2*x2
ми можемо сподіватися, що компілятор виявить, що його x2
можна сміливо розміщувати при f
поверненні (а не чекати, коли сміттєзбірник перейде до місця розташування x2
). По суті, ми просимо компілятор виконати аналіз евакуації, щоб перетворити розподіли в кучу зібраного сміття у виділення на стеку, де це можливо.
Це не надто необґрунтовано просити: компілятор jhc haskell робить це, хоча GHC - ні. Саймон Марлоу каже, що генераційний сміттєзбірник 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
в регіоні.
Поза Haskell
Хоча висновок про область корисний у певних випадках, як обговорювалося вище, здається, що складно ефективно примиритись з ледачою оцінкою (див. Коментарі Едварда Кметта та Саймона Пейтона Джонса ). Наприклад, розглянемо
f :: Integer -> Integer
f n = product [1..n]
Можна спокуситись виділити список [1..n]
на стек і розподілити його після f
повернення, але це було б катастрофічно: він змінився б f
із використання O (1) пам'яті (під збиранням сміття) на O (n) пам'яті.
У 1990-х та на початку 2000-х років велика робота була проведена над висновком регіону для суворої функціональної мови ML. Мадс Тофте, Ларс Біркедал, Мартін Елсман, Нільс Галленберг написали досить читаючу ретроспективу про свою роботу щодо виводу регіону, значну частину якої вони інтегрували в компілятор MLKit . Вони експериментували з чисто регіональним управлінням пам’яттю (тобто не збирачем сміття), а також гібридним управлінням пам’яті, що базується на регіонах / зібраним сміттям, і повідомили, що їхні програми тестування працювали «в 10 разів швидше і в 4 рази повільніше», ніж чисті сміття, зібрані версії.