对Haskell中数据结构的困惑

时间:2014-08-09 20:17:23

标签: haskell

我一直在阅读精彩的Learn You A Haskell,我来到关于类型和类型类的章节。我很困惑你如何模仿等级,就像你在古典语言中那样。 例如,我知道如果我想要一个“类”的武器,那么这样的事情是可能的:

data Weapon = 
  Sword  { sharpness :: Int, weight :: Int, name :: String } 
  | Mace { spikeyness :: Int, weight :: Int, name :: String }
  deriving (Eq)

这是一种做事的好方法吗? 如果这个方法是正确的,那么我很难看到你将如何为每个构造函数实现不同的行为:例如。如果你想以不同的方式展示武器,取决于它是剑还是锤子......

instance Show Weapon where 
  show w = "This is " ++ name w ++ ". It has a weight of " ++ (show $ weight w)

我知道这是可能的,但是如果我试图显示所有字段,这个函数遇到问题,因为剑不是spikey而且maces不锋利。我如何在Show类中为Maces和Swords创建不同的实例?

2 个答案:

答案 0 :(得分:10)

你可以在构造函数上进行模式匹配,如下所示:

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 ++ ...

你可以这样做,但也许你应该开始考虑你想用你的武器做什么(比如击中某个人的东西) - 所以相反你可以使用像calculateDamage这样的函数:

data Weapon = MkWeapon { calcDamage :: HeroStats -> Enemy -> Damage, ... }

然后你可以制造很多武器,例如:

sword :: Weapon
sword = MkWeapon (\ heroStats enemyStats -> strength heroStats - armor enemyStats)

或类似的东西。

答案 1 :(得分:3)

更一般地说,您可能对Tony Tavener's blog感兴趣关于用函数式语言实现游戏(在他的情况下是OCaml)。有很多有趣的想法,例如this post in particular演示了一种使用继承概念定义游戏元素数据库的模块化方法。