Pattern match data types and their nested name in Haskell
I have:
data Color = Blue | Green | Red | White | Yellow deriving (Eq,Ord)
And then
data Term = Color | ...
data Bag = Bag {
color :: Color
...
}
Now I want to be able to pattern match to make sure that the term 开发者_运维知识库given is a Color and if so check it's "value" (Blue/Green...). Something like this:
func :: Term -> Bag -> Bool
func (c :: Color) bag = (color bag) == c
But (c :: Color) does not seem to work.
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.
Here is a somewhat wordier account, no different in content from sdcvvc's, I think.
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
Notice that unlike sdcvvc I used "TColor Color". It's no different since the typechecker can tell that one is an already established type the other is a new constructor of a new type, even if they're spelled the same. It's just little less confusing. Something like "Color Color" would not be so uncommon these days, but in a older book like Bird's "Intro to FP with Haskell," he wouldn't do this sort of thing. It's a bit like the Haskeller's vogue for things like "\file -> readFile file" which has its advantages, but is potentially confusing and it seems pretty recent; formerly it would have been just \x -> readFile x or something.
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
Note also that in colorCheck
the bag is irrelevant. It isn't clear from what you say why you need the intermediate type Term.
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.
Results:
*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
精彩评论