Haskell · syntaxe · listes
Les compréhensions de listes en Haskell, expliquées
L’une des premières choses qui rendent Haskell élégant est la compréhension de liste : une façon concise de construire une nouvelle liste à partir de listes existantes, reflétant la notation mathématique en compréhension que vous vous rappelez peut-être de l’école. Ce guide explique la syntaxe, les générateurs multiples, les gardes, et le lien entre les compréhensions et map et filter.
La syntaxe de base
Une compréhension de liste a la forme [ output | generator, condition ]. Lisez la barre comme « tel que » :
-- the squares of 1 to 10
squares = [x*x | x <- [1..10]]
-- [1,4,9,16,25,36,49,64,81,100] Ici x <- [1..10] est un générateur : il tire chaque x de la liste [1..10], et la partie avant la barre, x*x, est l’expression de sortie appliquée à chaque élément.
Ajouter des gardes (filtrage)
Une garde est une condition booléenne qui ne conserve que les éléments qui la satisfont :
-- even numbers from 1 to 20, doubled
result = [x*2 | x <- [1..20], even x]
-- [4,8,12,16,20,24,28,32,36,40] Vous pouvez combiner plusieurs gardes, séparées par des virgules ; toutes doivent être vraies pour qu’un élément soit inclus.
Générateurs multiples
Avec plus d’un générateur, la compréhension itère sur chaque combinaison (comme des boucles imbriquées), dans l’ordre :
-- all pairs from two small lists
pairs = [(x, y) | x <- [1,2,3], y <- ['a','b']]
-- [(1,'a'),(1,'b'),(2,'a'),(2,'b'),(3,'a'),(3,'b')] Le générateur le plus à droite varie le plus vite. Vous pouvez aussi faire dépendre un générateur ultérieur d’un précédent — par exemple en tirant y de [x..10].
Leur lien avec map et filter
Une compréhension est essentiellement map et filter sous une forme lisible unique. Ceux-ci sont équivalents :
[x*2 | x <- xs, even x]
map (*2) (filter even xs) Utilisez ce qui se lit le mieux selon le cas. Les compréhensions brillent quand vous avez plusieurs générateurs ou plusieurs gardes ; map/filter se composent bien dans des pipelines point-free. Parce que Haskell est paresseux, une compréhension sur une liste infinie comme [1..] ne calcule que les éléments que vous consommez réellement.
FAQ
Qu’est-ce qu’un générateur dans une compréhension de liste ? La partie x <- xs : elle tire chaque valeur de x de la liste xs pour alimenter l’expression de sortie.
Qu’est-ce qu’une garde ? Une condition booléenne (comme even x) placée après une virgule ; seuls les éléments pour lesquels elle est vraie sont conservés.
Puis-je utiliser plusieurs générateurs ? Oui — la compréhension produit chaque combinaison, le générateur le plus à droite variant le plus vite, comme des boucles imbriquées.
Les compréhensions sont-elles juste map et filter ? Conceptuellement oui pour les cas simples ; les compréhensions sont souvent plus lisibles avec plusieurs générateurs ou gardes, tandis que map/filter se composent bien dans des pipelines.
Pour le langage derrière la syntaxe, voyez ce qu’est Haskell ; les compréhensions sont l’une des fonctionnalités qui le rendent concis et expressif.