Haskell - Pourquoi cette compréhension de liste retourne-t-elle une liste infinie?

Jan 15 2021
[3 * x | x <- [1 ..], 3 * x < 20]

Je ne comprends pas vraiment pourquoi cela donne

[3,6,9,12,15,18

Et ne trouve pas de fin

Réponses

14 chi Jan 15 2021 at 23:37

La sémantique de

[3 * x | x <- [1 ..], 3 * x < 20]

consiste à essayer tous les éléments [1..]et à conserver ceux qui satisfont à la condition de filtre 3*x<20.

Un humain peut voir qu'après le premier xqui falsifie la condition, il ne sert à rien d'essayer toutes les valeurs plus grandes, mais Haskell les essaiera quand même, et restera coincé sur une sorte de boucle infinie.

En effet, dans le cas général, la condition pourrait redevenir vraie, par exemple

[3 * x | x <- [1 ..], 3 * x < 20 || x == 1000000 ]

En général, il est indécidable de détecter s'il n'y a plus de solutions, donc Haskell, comme tout autre langage de programmation, ne peut pas choisir de s'arrêter après la dernière solution.

Si vous souhaitez que la liste s'arrête après la première valeur qui ne satisfait pas la condition de filtrage, utilisez takeWhile:

takeWhile (< 20) [3 * x | x <- [1 ..]]