Haskell · sintassi · liste
Le list comprehension in Haskell, spiegate
Una delle prime cose che rendono Haskell elegante è la list comprehension: un modo conciso per costruire una nuova lista a partire da liste esistenti, che riflette la notazione matematica per comprensione che forse ricordi dai banchi di scuola. Questa guida spiega la sintassi, i generatori multipli, le guardie e il legame tra le comprehension e map e filter.
La sintassi di base
Una list comprehension ha la forma [ output | generator, condition ]. Leggi la barra come «tale che»:
-- the squares of 1 to 10
squares = [x*x | x <- [1..10]]
-- [1,4,9,16,25,36,49,64,81,100] Qui x <- [1..10] è un generatore: estrae ogni x dalla lista [1..10], e la parte prima della barra, x*x, è l’espressione di output applicata a ciascun elemento.
Aggiungere guardie (filtraggio)
Una guardia è una condizione booleana che conserva solo gli elementi che la soddisfano:
-- 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] Puoi combinare più guardie, separate da virgole; tutte devono essere vere perché un elemento sia incluso.
Generatori multipli
Con più di un generatore, la comprehension itera su ogni combinazione (come cicli annidati), in ordine:
-- 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')] Il generatore più a destra varia più velocemente. Puoi anche far dipendere un generatore successivo da uno precedente — per esempio estraendo y da [x..10].
Il loro legame con map e filter
Una comprehension è essenzialmente map e filter in un’unica forma leggibile. Questi sono equivalenti:
[x*2 | x <- xs, even x]
map (*2) (filter even xs) Usa ciò che si legge meglio nel caso specifico. Le comprehension brillano quando hai più generatori o più guardie; map/filter si compongono bene in pipeline point-free. Poiché Haskell è lazy, una comprehension su una lista infinita come [1..] calcola solo gli elementi che effettivamente consumi.
FAQ
Cos’è un generatore in una list comprehension? La parte x <- xs: estrae ogni valore di x dalla lista xs per alimentare l’espressione di output.
Cos’è una guardia? Una condizione booleana (come even x) posta dopo una virgola; vengono conservati solo gli elementi per cui è vera.
Posso usare più generatori? Sì — la comprehension produce ogni combinazione, con il generatore più a destra che varia più velocemente, come cicli annidati.
Le comprehension sono solo map e filter? Concettualmente sì per i casi semplici; le comprehension sono spesso più leggibili con più generatori o guardie, mentre map/filter si compongono bene in pipeline.
Per il linguaggio dietro la sintassi, vedi cos’è Haskell; le comprehension sono una delle caratteristiche che lo rendono conciso ed espressivo.