我是一个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
Run Code Online (Sandbox Code Playgroud)
1)card.ValueConstructorName是幻想字段/方法/无论如何.有没有办法用卫兵来实现这个目标?
2)我真的需要在值构造函数的每个替代中键入"{cSuit :: Suit}"吗?
3)这种抽象卡牌是否合理?我的意思是,使用嵌套类型谢谢你
1)这称为模式匹配.
cardValue (Ace suit) = 11
cardValue (Seven suit) = 10
cardValue ....
Run Code Online (Sandbox Code Playgroud)
2)不.这是代表卡片的一种非常繁琐的方式.这里有一个非常明显的模式; 在haskell中,每当你看到一个非常重复的模式时,你可以保证有一些方法来抽象出来让事情变得更好.请尝试以下方法:
data Value = Ace | Two | Three | .... | King deriving (Show, Eq, Enum)
Run Code Online (Sandbox Code Playgroud)
这个最好的部分是你可以得到你Enum对这样一个数据类型,并Enum定义了一个函数fromEnum,将转换CardValue成Int.正如您所料,第0个构造函数将为0等,因此如果ace == 1则:
cardValue1 :: Value -> Int
cardValue1 x = 1 + fromEnum x
Run Code Online (Sandbox Code Playgroud)
然后你定义一张卡片:
data Card = Card Value Suit
Run Code Online (Sandbox Code Playgroud)
或者如果你真的想要记录:
data Card = Card {valueOfCard :: Value, suitOfCard :: Suit}
Run Code Online (Sandbox Code Playgroud)
但通常使用包含2个字段的数据类型的记录是没有意义的.甚至:
type Card = (Value, Suit)
Run Code Online (Sandbox Code Playgroud)
然后:
cardValue :: Card -> Int
cardValue (Card v _) = cardValue1 v
Run Code Online (Sandbox Code Playgroud)
3)'几乎所有'类型都是嵌套的.除了嵌套类型之外,您没有其他选择.有一些原始类型,你几乎肯定都看不到,其他类型只是这些原语的某种组合.