Haskell Language
Liste des compréhensions
Recherche…
Compréhension de la liste de base
Haskell a des compréhensions de listes , qui ressemblent beaucoup à des compréhensions d'ensemble en mathématiques et à des implémentations similaires dans des langages impératifs tels que Python et JavaScript. Dans leur forme la plus simple, les compréhensions de liste prennent la forme suivante.
[ x | x <- someList ]
Par exemple
[ x | x <- [1..4] ] -- [1,2,3,4]
Les fonctions peuvent aussi être appliquées directement à x:
[ f x | x <- someList ]
Ceci est équivalent à:
map f someList
Exemple:
[ x+1 | x <- [1..4]] -- [2,3,4,5]
Motifs dans les expressions du générateur
Cependant, x
dans l'expression du générateur n'est pas seulement variable, mais peut être n'importe quel modèle. En cas de non concordance de modèle, l'élément généré est ignoré et le traitement de la liste continue avec l'élément suivant, agissant ainsi comme un filtre:
[x | Just x <- [Just 1, Nothing, Just 3]] -- [1, 3]
Un générateur avec une variable x
dans son modèle crée une nouvelle étendue contenant toutes les expressions à sa droite, où x
est défini comme étant l'élément généré.
Cela signifie que les gardes peuvent être codés comme
[ x | x <- [1..4], even x] ==
[ x | x <- [1..4], () <- [() | even x]] ==
[ x | x <- [1..4], () <- if even x then [()] else []]
Gardes
Une autre caractéristique de la compréhension de liste est celle des gardes, qui servent également de filtres. Les gardes sont des expressions booléennes et apparaissent sur le côté droit de la barre dans une liste de compréhension.
Leur utilisation la plus élémentaire est
[x | p x] === if p x then [x] else []
Toute variable utilisée dans un garde doit apparaître à sa gauche dans la compréhension ou être dans la portée. Alors,
[ f x | x <- list, pred1 x y, pred2 x] -- `y` must be defined in outer scope
ce qui équivaut à
map f (filter pred2 (filter (\x -> pred1 x y) list)) -- or,
-- ($ list) (filter (`pred1` y) >>> filter pred2 >>> map f)
-- list >>= (\x-> [x | pred1 x y]) >>= (\x-> [x | pred2 x]) >>= (\x -> [f x])
(l'opérateur >>=
est infixl 1
, c'est-à-dire qu'il est associé (est mis entre parenthèses) à gauche). Exemples:
[ x | x <- [1..4], even x] -- [2,4]
[ x^2 + 1 | x <- [1..100], even x ] -- map (\x -> x^2 + 1) (filter even [1..100])
Générateurs imbriqués
Les compréhensions de listes peuvent également dessiner des éléments de plusieurs listes, auquel cas le résultat sera la liste de toutes les combinaisons possibles des deux éléments, comme si les deux listes étaient traitées de manière imbriquée . Par exemple,
[ (a,b) | a <- [1,2,3], b <- ['a','b'] ]
-- [(1,'a'), (1,'b'), (2,'a'), (2,'b'), (3,'a'), (3,'b')]
Compréhensions parallèles
Avec l'extension de langage Parallel List Comprehensions ,
[(x,y) | x <- xs | y <- ys]
est équivalent à
zip xs ys
Exemple:
[(x,y) | x <- [1,2,3] | y <- [10,20]]
-- [(1,10),(2,20)]
Liaisons locales
Les compréhensions de liste peuvent introduire des liaisons locales pour les variables afin de contenir certaines valeurs intermédiaires:
[(x,y) | x <- [1..4], let y=x*x+1, even y] -- [(1,2),(3,10)]
Le même effet peut être obtenu avec une astuce,
[(x,y) | x <- [1..4], y <- [x*x+1], even y] -- [(1,2),(3,10)]
La let
dans la liste compréhensions est récursive, comme d' habitude. Mais les liaisons de générateur ne le sont pas, ce qui permet l' observation :
[x | x <- [1..4], x <- [x*x+1], even x] -- [2,10]
Notation
Toute compréhension de liste peut être en correspondance codé avec la liste monade de do
notation .
[f x | x <- xs] f <$> xs do { x <- xs ; return (f x) }
[f x | f <- fs, x <- xs] fs <*> xs do { f <- fs ; x <- xs ; return (f x) }
[y | x <- xs, y <- f x] f =<< xs do { x <- xs ; y <- f x ; return y }
Les gardes peuvent être manipulés en utilisant Control.Monad.guard
:
[x | x <- xs, even x] do { x <- xs ; guard (even x) ; return x }