coldwa.st
Tutte le guideProgrammazioneWebDatiStrumentiDatabaseHaskellConcettiCabal e buildToolchainCompilatorePrestazioniEditor e HLS

Haskell · sintassi · liste

Le list comprehension in Haskell, spiegate

Di ColdwastAggiornato il 14 giugno 20266 min di lettura#haskell#lists#syntax
Codice sorgente su uno schermo
Codice sorgente su uno schermo — le list comprehension sono un modo conciso per costruire liste nel codice.

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)

Righe di codice sorgente su uno schermo scuro
Righe di codice sullo schermo — una guardia conserva solo gli elementi che soddisfano una condizione.

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.

Guida indipendente, mantenuta dalla community. coldwa.st è un sito di risorse sulla programmazione; questo articolo è uno scritto esplicativo nuovo e originale sulle list comprehension in Haskell, senza alcuna affiliazione con i maintainer del linguaggio. Il codice riflette il comportamento standard di Haskell/GHC — verifica con la documentazione GHC attuale.