Benjamin Gorman
Benjamin Gorman

Reputation: 370

Confusion over data structures in Haskell

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

Answers (2)

gallais
gallais

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

Random Dev
Random Dev

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 calculateDamageon 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

Related Questions