Reputation: 370
I've been reading the brilliant Learn You A Haskell and I've come to the chapter on types and type classes. I'm confused as to how you would imitate hierarchy as you would in a classical language. For example, I know if I want a 'class' of weapons then something like this is possible:
data Weapon =
Sword { sharpness :: Int, weight :: Int, name :: String }
| Mace { spikeyness :: Int, weight :: Int, name :: String }
deriving (Eq)
Is this a good way to do things? If this method is correct, then I'm struggling to see how you would implement different behaviour for each constructor: E.g. if you wanted to show a weapon in a different way depending on whether it was a Sword or a Mace...
instance Show Weapon where
show w = "This is " ++ name w ++ ". It has a weight of " ++ (show $ weight w)
I know this is possible, but this function encounters a problem if I try to show all the fields because swords are not spikey and maces are not sharp. How could I create different instances in the Show class for Maces and Swords?
Upvotes: 2
Views: 137
Reputation: 12093
On a more general note, you may be interested in Tony Tavener's blog about implementing a game in a functional language (OCaml in his case). There are a lot of interesting ideas e.g. this post in particular demonstrating a modular way of defining a database of game elements with a notion of inheritance.
Upvotes: 3
Reputation: 52270
Well you can pattern-match on the constructor like this:
instance Show Weapon where
show (Sword s w n) = "This is a sword with sharpness " ++ show s ++ ...
show (Mace s w n ) = "This is a mace with spikeyness " ++ show s ++ ...
and you can do it like this but maybe you should start to think what you want to do with your weapons (like hit somebody, something) - so instead you could have functions like calculateDamage
on them:
data Weapon = MkWeapon { calcDamage :: HeroStats -> Enemy -> Damage, ... }
And then you can make lot's of weapons, for example:
sword :: Weapon
sword = MkWeapon (\ heroStats enemyStats -> strength heroStats - armor enemyStats)
or something like this.
Upvotes: 10