2009-10-03 4 views
0

J'ai:types de données de correspondance de motif et leur nom imbriqué dans Haskell

data Color = Blue | Green | Red | White | Yellow deriving (Eq,Ord) 

Et puis

data Term = Color | ... 
data Bag = Bag { 
color :: Color 
... 
} 

Maintenant, je veux être en mesure de correspondance de motif pour faire en sorte que le terme donné est un Couleur et si oui, vérifiez que c'est "valeur" (Bleu/Vert ...). Quelque chose comme ceci:

func :: Term -> Bag -> Bool 
func (c :: Color) bag = (color bag) == c 

Mais (c :: Color) ne semble pas fonctionner.

+7

Cela semble être un malentendu débutants un peu commun: le type nommé 'Color' (de' données Color') et le constructeur nommé 'Color' (de' données Term = Color') sont complètement indépendants, dans des espaces de noms complètement différents. – ephemient

+1

@ephemien J'aurais accepté cette réponse. –

Répondre

8
data Color = Blue | Green | Red | White | Yellow deriving (Eq,Ord) 

data Term = Color Color | Trash 

data Bag = Bag { 
    color :: Color 
} 

func (Color x) bag = (color bag) == x 

-- With the above, a call of func Trash something will fail. 
-- (unexhastive pattern match). You can add 

func Trash bag = False 

-- or 

func _ _ = False 

-- and it will work all time. 
2

Voici un compte un peu plus wordier, pas différent dans le contenu de sdcvvc, je pense.

 
data Color = Blue | Green | Red | White | Yellow deriving (Eq,Ord,Show) 
data Size = Small | Medium | Large deriving (Eq, Ord, Show) 

data Term = TColor Color | TSize Size | Trash deriving Show 
data Bag = Bag {color :: Color , size :: Size} deriving Show 

Notez que contrairement à sdcvvc, j'ai utilisé "TColor Color". Ce n'est pas différent puisque le typechecker peut dire que l'un est un type déjà établi, l'autre est un nouveau constructeur d'un nouveau type, même s'ils sont orthographiés de la même façon. C'est juste un peu moins déroutant. Quelque chose comme "Color Colour" ne serait pas si rare de nos jours, mais dans un livre plus ancien comme "Intro to FP with Haskell" de Bird, il ne ferait pas ce genre de chose. C'est un peu comme la vogue de Haskeller pour des choses comme "\ file -> fichier readFile" qui a ses avantages, mais qui est potentiellement confus et qui semble assez récent; auparavant, il aurait juste été \ x -> readFile x ou quelque chose.

 
theMrsThatcher :: Bag 
theMrsThatcher = Bag Blue Large 

theMrsRobinson :: Bag 
theMrsRobinson = Bag {color = Green, size = Small} -- to use the other syntax 

colorCheck :: Term -> Bag -> Bool 
colorCheck (TColor c) b = True 
colorCheck (TSize s) b = False -- as sdcvvc says, this and 
colorCheck Trash b = False  -- the next clause can be replaced by 
           -- colorCheck _ _ = False 

On notera également que dans colorCheck le sac est hors de propos. Il n'est pas clair d'après ce que vous dites pourquoi vous avez besoin du type intermédiaire Terme.

 
colorTest :: Color -> Bag -> Bool 
colorTest c b = color b == c 

colorCheckTest :: Term -> Bag -> Bool 
colorCheckTest (TColor c) b = color b == c 
colorCheckTest (TSize s) b = False -- as above, the last clauses are 
colorCheckTest Trash b = False  -- wordier than need be since any 
             -- but the first pattern is a loser. 

Résultats:

 
*Main> colorCheck (TColor Blue) theMrsRobinson 
True 
*Main> colorCheck (TColor Blue) theMrsThatcher 
True 
*Main> colorCheckTest (TColor Blue) theMrsRobinson 
False 
*Main> colorCheckTest (TColor Blue) theMrsThatcher 
True 
*Main> colorTest Blue theMrsThatcher 
True 
*Main> colorTest Blue theMrsRobinson 
False 
Questions connexes