2010-05-08 11 views
10

Un problema comune che ho ottenuto in Haskell è quello di estrarre tutti i termini in un elenco appartenente a un costruttore di dati specifico e mi chiedo se ci sono modi migliori rispetto al come lo sto facendo al momentoCome estrarre i termini del costruttore di dati specifici da un elenco in Haskell

Diciamo che hai

data Foo = Bar | Goo 

, la lista

foos = [Bar, Goo, Bar, Bar, Goo] 

e desidera estrarre tutti Goo s da foos. Al momento di solito faccio qualcosa come

goos = [Goo | Goo <- foos] 

e tutto va bene. Il problema è quando Goo ha ottenuto una serie di campi e sono costretto a scrivere qualcosa di simile

goos = [Goo a b c d e f | Goo a b c d e f <- foos] 

che è ben lungi dall'essere ideale. Di solito come gestisci questo problema?

risposta

20

Sembra che ci sono due parti a questa domanda:

  1. C'è un modo più semplice per fare pattern matching
  2. Sono list comprehension ok qui?

primo luogo, v'è un modo migliore per abbinare su campi che non si cura di:

goos = [ x | [email protected](Goo {}) <- foos] 

In secondo luogo, utilizzando list comprehension è un modo perfettamente cromulent di scrivere questi tipi di filtri. Ad esempio, nella libreria di base, catMaybes è definito come:

catMaybes :: [Maybe a] -> [a] 
catMaybes ls = [x | Just x <- ls] 

(dalla libreria di base). Quindi quell'idioma va bene.

+0

Ma OP vuole qualcosa di simile a '[Solo x | Solo x <- ls] ', non' catMaybes' o 'rights'. – kennytm

+0

Va bene, la domanda è in due parti: se la comprensione delle liste è ok, e in secondo luogo, quale forma di abbinamento dei modelli. Chiarirò –

4

Si potrebbe utilizzare

[x | [email protected](Goo _ _ _ _ _ _) <- foos] 

Si potrebbe anche definire un

isGoo :: Foo -> Bool 
isGoo (Goo _ _ _ _ _ _) = True 
isGoo _ = False 

e quindi utilizzare filter

filter isGoo foos 

o

[x | x <- foos, isGoo] 
Problemi correlati