发现在值中使用了哪个VALUE构造函数

时间:2014-01-07 20:33:56

标签: haskell

我是一个OOP /势在必行的程序员,正在尝试学习haskell,我正在开发一种卡片游戏作为练习。

当时,我试图定义库牌组:

data Suit = Hearts
      | Diamonds
      | Spades
      | Clubs
        deriving(Show, Eq)

type CardValue = Int

data Card = Ace   {cSuit :: Suit}
          | Two   {cSuit :: Suit}
          | Three {cSuit :: Suit}
          | Four  {cSuit :: Suit}
          | Five  {cSuit :: Suit}
          | Six   {cSuit :: Suit}
          | Seven {cSuit :: Suit}
          | Eight {cSuit :: Suit}
          | Nine  {cSuit :: Suit}
          | Ten   {cSuit :: Suit}
          | Jack  {cSuit :: Suit}
          | Queen {cSuit :: Suit}
          | King  {cSuit :: Suit}
            deriving(Show, Eq)

type Hand = [Card]
type Deck = [Card]

cardValue :: Card -> Int
cardValue card =
      | card.ValueConstructorName == Ace   = 11
      | card.ValueConstructorName == Seven = 10
      | otherwise                          = 0

1)card.ValueConstructorName是幻想字段/方法/其他。有没有办法用卫兵来实现这个目标?

2)我是否真的需要在值构造函数的每个替代中键入“{cSuit :: Suit}”?

3)这种抽象卡牌是否合理?我的意思是,使用嵌套类型 谢谢你

2 个答案:

答案 0 :(得分:8)

1)这称为模式匹配。

cardValue (Ace suit) = 11
cardValue (Seven suit) = 10
cardValue  ....

2)不。这是代表卡片的一种非常繁琐的方式。这里有一个非常明显的模式;在haskell中,每当你看到一个非常重复的模式时,你可以保证有一些方法来抽象出来以使事情变得更好。请尝试以下方法:

data Value = Ace | Two | Three | .... | King deriving (Show, Eq, Enum)

关于此问题的最佳部分是,您可以为此类数据类型派生EnumEnum定义一个名为fromEnum的函数,该函数会将CardValue转换为Int。正如您所料,第0个构造函数将为0等,因此如果ace == 1则为:

cardValue1 :: Value -> Int
cardValue1 x = 1 + fromEnum x

然后你定义一张卡片:

data Card = Card Value Suit

或者如果你真的想要记录:

data Card = Card {valueOfCard :: Value, suitOfCard :: Suit}

但通常使用包含2个字段的数据类型的记录是没有意义的。甚至:

type Card = (Value, Suit)

然后:

cardValue :: Card -> Int
cardValue (Card v _) = cardValue1 v

3)'几乎所有'类型都是嵌套的。除了嵌套类型之外,您没有其他选择。有一些原始类型,你几乎肯定都看不到,其他类型只是这些原语的某种组合。

答案 1 :(得分:0)

您需要的是模式匹配:

cardValue :: Card -> Int
cardValue (Ace suit) = ...
cardValue (Two suit) = ...
cardValue (Three suit) = ...
...

你可以这个或一个案例陈述

cardValue :: Card -> Int
cardValue card = case card of
    Ace suit -> ...
    Two suit -> ...
    ...

至于这是否是一个好模型,我会建议反对它。 user2407038显示的方式是更好的选择,特别是与EnumBounded类型组合时。