6
votes

(++) opérateur et (:) opérateur et évaluation paresseux

Chapitre 8 du Realworldhakell
(++) :: [a] -> [a] -> [a]

(x:xs) ++ ys = x : (xs ++ ys)
[]     ++ ys = ys


1 commentaires

Cela me semble que l'espace constant vient de jeter x lors de la génération du prochain xs sur demande.


3 Réponses :


5
votes

La récursion de la queue garderait la constante de la pile, mais dans une langue stricte, le tas augmenterait comme x: (xs ++ ys) a été calculé. Dans HASKELLL, car il est non strict, x serait libéré avant que la valeur suivante ait été calculée (sauf si l'appelant détenait une référence à x inutilement), donc le tas aussi être constant.


0 commentaires

8
votes

N'oubliez pas que "foo" est juste du sucre syntaxique pour 'F': 'O': 'O': [] .

c'est-à-dire, string est juste un alias pour [caractère] qui n'est qu'une liste liée des caractères.

Lorsque le code client est consommant la liste liée, il le décompose dans une tête et une queue (par exemple, x: xs ), fait quelque chose avec la tête (si désiré ), puis recute pour la queue.

Lorsque votre code est construisant la liste liée, en raison de l'évaluation paresseuse, tout ce qu'il doit faire est de retourner un thunk ou de promettre qu'il retournera une liste liée lorsque demandé. Lorsque la tête est déréférencée, elle est fournie à la demande et la queue est laissée comme une promesse pour le reste de la liste.

Il devrait être facile de voir que tant que la liste n'est pas copiée ou autrement stockée, chaque Thunk sera utilisé une fois, puis rejeté, de sorte que l'espace de stockage global soit constant.

De nombreuses langues strictes exposent un mécanisme (souvent appelé un générateur ) pour accomplir le même type de génération de liste paresseuse, mais avec une évaluation paresseuse, de telles caractéristiques sont "gratuites" dans le cadre de la langue - En substance, toutes les listes de haskell sont des générateurs!


0 commentaires

7
votes

S'appuyant sur l'évaluation paresseux plutôt que sur la récursion de la queue est une caractéristique de HASKELLL par rapport à d'autres langues PF. Les deux rôles liés au jeu en termes de limitation de la mémoire; Lequel est le mécanisme approprié dépend des données produites.

Si votre sortie peut être consommée progressivement, vous devriez préférer tirer parti de l'évaluation paresseuse, car la sortie ne sera générée que si nécessaire, limitant ainsi la consommation de tas. Si vous construisez avec impatience la sortie, vous vous démissez à l'aide de tas, mais vous pouvez au moins conserver la pile en étant récursif de queue.

Si votre sortie ne peut pas être consommée progressivement - vous êtes peut-être calculé un int - alors la paresseux peut vous laisser avec une pile indésirable de thunks dont l'évaluation va souffler votre pile. Dans ce cas, un accumulateur strict et une récursion queue sont appelés.

Donc, si vous êtes impatient, vous risquez de perdre des tas bâtiment une grande structure de données. Si vous êtes paresseux, vous risquez de différer SIMPLIFICIFICATION (par exemple, réduction 1 + 1 à 2 ) sur le tas, seulement pour finalement souiller votre pile quand Payer le Piper.

Pour jouer avec les deux côtés de la pièce, réfléchissez pli " et replier .


0 commentaires