
On Sun, Aug 30, 2009 at 2:32 PM, Patrick
LeBoutillier
volume :: Fruit FruitType -> Double volume F{radius=r,len=l,fType=Orange} = (4.0/3.0) * pi * r * r * r
volume F{radius=r,len=l,fType=Apple} = (4.0/3.0) * pi * r * r * r volume F{radius=r,len=l,fType=Banana} = pi * (r * r) * l volume F{radius=r,len=l,fType=Watermelon} = (4.0/3.0) * pi * (2.0 * r) * l * (0.5 * l)
Can anyone explain the above pattern matching syntax? I've never seen it before...
It's part of what record syntax allows : record pattern. record_pattern = data_constructor '{' (field_pattern ',')* '}' field_pattern = field_name '=' pattern You don't have to use all the fields of the datatype in a pattern if you don't need them all. A special case is when you put zero field_pattern in the {}, in this case you can even use this syntax for regular datatype (no record syntax), to write thing like :
isJust Just {} = True isJust _ = False
(especially interesting for constructors with plenty of parameters, of course) ----------- To come back to the initial subject, if you use datatypes and typeclass rather than dataconstructors and pattern matching to allow extensibility of data, you can still have a list of different fruits type, using existential types, though that is not without minus :
data Fruit a = F { radius, length :: Double } data Orange; data Banana;
class Volume a where vol :: a -> Double
instance Volume (Fruit Orange) where vol (F r _) = (4/3) * pi * r * r * r instance Volume (Fruit Banana) where vol (F r l) = pi * (r * r) * l
data Volumic = Volume a => V a
fruit_list :: [Volumic] fruit_list = [V (F 3 undefined :: Fruit Orange), V (F 1 6 :: Fruit Banana) ]
In this particular case it is really uninteresting since you could as well stock a list of volumes (the only thing you can do with a Volumic is get the volume of its content) but with more versatile typeclass, it may be different. -- Jedaï