Pourquoi la fonction "ne rien faire" de Haskell, id, consomme-t-elle des tonnes de mémoire?

Haskell a une fonction d'identité qui renvoie l'entrée inchangée. La définition est simple:

id :: a -> a
id x = x

Donc, pour le plaisir, cela devrait sortir 8:

f = id id id id id id id id id id id id id id id id id id id id id id id id id id id
main = print $ f 8

Après quelques secondes (et environ 2 Go de mémoire selon le Gestionnaire des tâches), la compilation échoue avec ghc: out of memory. De même, l'interprète dit ghci: out of memory.

Puisque id est une fonction assez simple, Je ne m'attendrais pas à ce que ce soit un fardeau de mémoire au moment de l'exécution ou de la compilation. Qu'est-ce que la mémoire utilisée pour?

110
demandé sur Ryan 2014-05-20 00:41:56

1 réponses

Nous connaissons le type de id,

id :: a -> a

Et quand nous nous spécialisons ce pour id id, le gauche copie de id a type:

id :: (a -> a) -> (a -> a)

Et puis quand vous vous spécialisez à nouveau pour le id le plus à gauche dans id id id, vous obtenez:

id :: ((a -> a) -> (a -> a)) -> ((a -> a) -> (a -> a))

Ainsi, vous voyez chaque id que vous ajoutez, la signature de type du id le plus à gauche est deux fois plus grande.

Notez que les types sont supprimés lors de la compilation, donc cela ne prendra que de la mémoire dans GHC. Il ne prendra pas de mémoire dans votre programme.

130
répondu Dietrich Epp 2014-05-19 20:52:24