开发者

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  
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜