2010-05-08 5 views
10

Un problème courant que j'ai eu dans Haskell est d'extraire tous les termes d'une liste appartenant à un constructeur de données spécifique et je me demande s'il existe de meilleurs moyens que le comme je le fais en ce moment.Comment extraire des termes de constructeur de données spécifiques à partir d'une liste dans Haskell

Disons que vous avez

data Foo = Bar | Goo 

, la liste

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

et souhaitez extraire tous les Goo s de foos. En ce moment je fais quelque chose comme

goos = [Goo | Goo <- foos] 

et tout va bien. Le problème est quand Goo a obtenu un tas de champs et je suis obligé d'écrire quelque chose comme

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

qui est loin d'être idéale. Comment gérez-vous habituellement ce problème?

Répondre

20

On dirait qu'il ya deux parties à cette question:

  1. est-il un moyen plus facile de faire la correspondance de modèles
  2. sont-liste compréhensions ok ici?

Tout d'abord, il est une meilleure façon de faire correspondre les champs que vous ne se soucient pas:

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

En second lieu, en utilisant compréhensions de la liste est une façon parfaitement cromulent d'écrire ces types de filtres. Par exemple, dans la bibliothèque de base, catMaybes est défini comme:

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

(à partir de la bibliothèque de base). Donc, cet idiome est bien.

+0

Mais OP veut quelque chose de similaire à '[Just x | Juste x <- ls] ', pas' catMaybes' ou 'rights'. – kennytm

+0

Très bien, la question est en deux parties: si les compréhensions de liste sont correctes, et deuxièmement, quelle forme de correspondance de modèle. Je vais clarifier. –

4

Vous pouvez utiliser

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

Vous pouvez également définir un

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

puis utilisez filter

filter isGoo foos 

ou

[x | x <- foos, isGoo] 
Questions connexes