
On Thu, 23 Oct 2008 11:48:46 +0200, Daniel Fischer
Am Donnerstag, 23. Oktober 2008 10:51 schrieb Benjamin L.Russell:
After taking your advice into account, I have rewritten the wine.hs program as follows, but am unable to figure out what to write for the type constructor for Wine. In particular, I do not understand why the user type definition for Wine is "Red Red | White White" instead of just "Red | White."
Okay, that was a bit mean, but not intentionally.
In GADT syntax: data Wine where Red :: Red -> Wine White :: White -> Wine
So there is a dataconstructor called Red and also a datatype (I was tempted to write typeconstructor) called Red and the dataconstructor Red takes an argument of type Red, similarly for White. The type Wine is isomorphic to Either Red White, but since that wouldn't give a good Show instance, we roll our own type.
If we had just data Wine = Red | White , the type Wine would have just the two members Red and White (and _|_) and not have any connection with the types Red and White which give the details (grape/origin). We need a means to transform a value of type Red into a value of type Wine, that is a function of type Red -> Wine, the application demands that that function doesn't lose information, that is best achieved by a dataconstructor of type Red -> Wine. Would probably have been less confusing if I called the dataconstructors RedWine resp. WhiteWine.
Thank you. That makes the Wine much clearer ;-) .
[...]
You have basically two choices, you can say everybody knows which colour the wines have and use
instance Show Wine where show (Red w) = show w show (White w) = show w
or include the colour in the rendered String, for example via deriving Show, or by declaring your own instance (if you want White PinotNoir rendered as "White (Pinot Noir)", you would have to do that or write a more complicated Show instance for White). If you want to parse values of type Wine in the future, it will be slightly easier with the dataconstructors included.
So perhaps I should rewrite the type definitions for Red and White as follows? data Red = Syrah | Merlot | Port deriving (Eq, Show) data White = SauvignonBlanc | Riesling | PinotNoir deriving (Eq, Show) Alternatively (adapted from an example provided by Dirk Thierbach in the thread "seeking helpful links," dated "Tue, 21 Oct 2008 16:33:41 -0700 (PDT)," on comp.lang.haskell), perhaps the following? type Entree = String type SideDish = String type Wine = String wine :: Entree -> SideDish -> Wine wine "Kobe Beef" "Buttered Potatoes" = "Syrah" wine "Kobe Beef" "Brie Cheese" = "Syrah" wine "Kobe Beef" "Greek Salad" = "Sauvignon Blanc" wine "Lemon Chicken" "Buttered Potatoes" = "Merlot" wine "Lemon Chicken" "Brie Cheese" = "Sauvignon Blanc" wine "Lemon Chicken" "Greek Salad" = "Merlot" wine "Steamed Salmon" "Buttered Potatoes" = "Sauvignon Blanc" wine "Steamed Salmon" "Brie Cheese" = "Port" wine "Steamed Salmon" "Greek Salad" = "Port" wines :: [Entree] -> [SideDish] -> [(Entree, SideDish, Wine)] wines entrees sideDishes = [(e, s, wine e s) | e <- entrees, s <- sideDishes]
[...]
Bon Appetit, Daniel
P.S.: Could I have a Syrah with my beef and potatoes?
Certainly; here is your Syrah with your beef and potatoes. Bon appetit ;-) : module Wine where data Wine = Red Red | White White data Red = Syrah | Merlot | Port data White = SauvignonBlanc | Riesling | PinotNoir data Entree = KobeBeef | LemonChicken | SteamedSalmon deriving (Eq, Enum, Bounded) data SideDish = ButteredPotatoes | BrieCheese | GreekSalad deriving (Eq, Enum, Bounded) instance Show Wine where show (Red w) = show w show (White w) = show w instance Show Red where show Syrah = "Syrah" show Merlot = "Merlot" show Port = "Port" instance Show White where show SauvignonBlanc = "Sauvignon Blanc" show Riesling = "Riesling" show PinotNoir = "Pinot Noir" instance Show Entree where show KobeBeef = "Kobe Beef" show LemonChicken = "Lemon Chicken" show SteamedSalmon = "Steamed Salmon" instance Show SideDish where show ButteredPotatoes = "Buttered Potatoes" show BrieCheese = "Brie Cheese" show GreekSalad = "Greek Salad" selectWine :: Entree -> SideDish -> Wine selectWine KobeBeef sd = case sd of GreekSalad -> White SauvignonBlanc _ -> Red Syrah selectWine LemonChicken sd = case sd of BrieCheese -> White Riesling _ -> Red Merlot selectWine SteamedSalmon sd = case sd of ButteredPotatoes -> White PinotNoir _ -> Red Port options :: [(Entree,SideDish,Wine)] options = [(e,s,selectWine e s) | e <- [minBound .. maxBound], s <- [minBound .. maxBound]] Here's your new menu: *Wine> :l wine2.hs [1 of 1] Compiling Wine ( wine2.hs, interpreted ) Ok, modules loaded: Wine. *Wine> options [(Kobe Beef,Buttered Potatoes,Syrah),(Kobe Beef,Brie Cheese,Syrah),(Kobe Beef,Gr eek Salad,Sauvignon Blanc),(Lemon Chicken,Buttered Potatoes,Merlot),(Lemon Chick en,Brie Cheese,Riesling),(Lemon Chicken,Greek Salad,Merlot),(Steamed Salmon,Butt ered Potatoes,Pinot Noir),(Steamed Salmon,Brie Cheese,Port),(Steamed Salmon,Gree k Salad,Port)] *Wine> -- Benjamin L. Russell