[Haskell-beginners] Re: how to define a user datatype consisting of
instances of String?
Benjamin L.Russell
DekuDekuplex at Yahoo.com
Thu Oct 23 06:19:32 EDT 2008
On Thu, 23 Oct 2008 11:48:46 +0200, Daniel Fischer
<daniel.is.fischer at web.de> wrote:
>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
More information about the Beginners
mailing list