Comme d'autres l'ont déjà souligné, Haskell nécessite automatique, dynamique de gestion de la mémoire: gestion automatique de la mémoire est nécessaire parce que le manuel de gestion de la mémoire est dangereux; gestion dynamique de la mémoire est nécessaire parce que, pour certains programmes, la durée de vie d'un objet ne peut être déterminée qu'au moment de l'exécution.
Par exemple, considérons le programme suivant:
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
Dans ce programme, la liste [1..1000]
doivent être conservés en mémoire jusqu'à ce que l'utilisateur tape "clair"; de sorte que la durée de vie de ce doit être déterminé de façon dynamique, et c'est pourquoi la gestion dynamique de la mémoire est nécessaire.
Ainsi, dans ce sens, automatisé allocation dynamique de la mémoire est nécessaire, dans la pratique, cela signifie: oui, Haskell nécessite un garbage collector, depuis la collecte des ordures est de la plus haute performance dynamique et automatique du gestionnaire de mémoire.
Cependant...
Bien qu'un garbage collector est nécessaire, nous pourrions essayer de trouver des cas particuliers dans lesquels le compilateur peut utiliser un meilleur gestion de la mémoire système de collecte des ordures. Par exemple, étant donné
f :: Integer -> Integer
f x = let x2 = x*x in x2*x2
on peut espérer pour le compilateur de détecter qu' x2
peuvent en toute sécurité être libéré lorsque f
rendements (plutôt que d'attendre que le garbage collector pour désallouer x2
). En fait, nous demandons que le compilateur d'effectuer échapper à l'analyse de convertir des allocations dans les déchets collectés sur le segment de mémoire à allouer sur la pile dans la mesure du possible.
Ce n'est pas trop déraisonnable de demander: le jhc compilateur haskell cela, bien que GHC ne le fait pas. Simon Marlow dit que GHC est générationnel garbage collector fait échapper à l'analyse de la plupart inutiles.
jhc utilise en fait une forme sophistiquée de s'échapper de l'analyse connu comme la région de l'inférence. Envisager
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
Dans ce cas, une simple échapper à l'analyse de conclure que l' x2
s'en échappe f
(parce qu'il est retourné dans le tuple), et par conséquent x2
doit être réparti sur les déchets collectés sur le tas. Région d'inférence, d'autre part, est capable de détecter x2
peut être libéré lors de l' g
rendements; l'idée est qu' x2
devraient être alloués g
's de la région plutôt que d' f
's de la région.
Au-Delà De Haskell
Alors que la région de l'inférence est utile, dans certains cas, comme discuté ci-dessus, il apparaît difficile de concilier efficacement avec d'évaluation différée (voir Edward Kmett de et Simon Peyton Jones commentaires). Par exemple, considérons
f :: Integer -> Integer
f n = product [1..n]
On pourrait être tenté d'attribuer le liste [1..n]
sur la pile et le désallouer après f
de rendement, mais cela serait catastrophique: il changerait f
de l'aide O(1) de la mémoire (en vertu de la collecte des ordures) à O(n) de la mémoire.
Travail considérable a été fait dans les années 1990 et au début des années 2000 sur la région de l'inférence pour la stricte langage fonctionnel ML. Mads Tofte, Lars Birkedal, Martin Elsman, Niels Hallenberg ont écrit un assez lisible rétrospective de leurs travaux sur la région de l'inférence, beaucoup de qui ils intégrés dans les MLKit compilateur. Ils ont expérimenté avec purement la région de base de la gestion de la mémoire (c'est à dire pas de garbage collector) ainsi que des hybrides de la région/le garbage collector de gestion de la mémoire, et ont indiqué que leurs programmes de test couru "entre 10 fois plus rapide, et 4 fois plus lent" que de purs déchets collectés versions.