我想在F#中代表standard playing cards。我的目标是实现Microsoft Solitaire(Windows附带的一个)的克隆,这是一个卡片'西装,面部和颜色很重要。这个练习主要是为了学习一些F#。
我考虑过使用歧视的工会:
type Suit =
| Diamonds
| Hearts
| Clubs
| Spades
type Color =
| Red
| Black
type Face =
Two | Three | Four | Five | Six | Seven |
Eight | Nine | Ten | Jack | Queen | King | Ace
卡的记录类型:
type Card = {
suit: Suit;
face: Face;
color: Color;
}
然而,卡片的颜色可以从它的套装中推断出来 - 所有钻石和红心都是红色的,所有的俱乐部和黑桃都是黑色的。不能仅从Color确定套装。也许这样的事情是恰当的:
type Suit =
| Diamonds of Color //should always be red
| Hearts of Color //should always be red
| Clubs of Color //should always be black
| Spades of Color //should always be black
type Face =
Two | Three | Four | Five | Six | Seven |
Eight | Nine | Ten | Jack | Queen | King | Ace
type Card = {
suit: Suit;
face: Face;
}
但这似乎并不合适,因为这样可以实现不正确的组合,例如:黑心和红锹。
我的问题是:
答案 0 :(得分:16)
由于始终可以从Color
推断出Suit
,因此没有理由明确地对其进行建模;你想要illegal states unrepresentable。
您仍然可以从模型中获得良好的编程体验,并且使用Active Pattern:
可以很好地建模颜色。type Suit =
| Diamonds
| Hearts
| Clubs
| Spades
let (|Red|Black|) suit =
match suit with
| Diamonds | Hearts -> Red
| Clubs | Spades -> Black
这将使您能够在Suit
上进行模式匹配,就像这个简单的例子:
let printColor card =
match card.Suit with
| Red -> "Red"
| Black -> "Black"
FSI的使用示例:
> printColor { Suit = Spades; Face = Ace };;
val it : string = "Black"
> printColor { Suit = Diamonds; Face = King };;
val it : string = "Red"
答案 1 :(得分:2)
您可以添加录制方法:
type Card =
{suit: Suit;face: Face}
member this.Color =
match this.suit with
| Diamonds | Hearts -> Red
| Clubs | Spades -> Black
示例:
let v = {suit = Diamonds;face = Two}
printfn "%A" v.Color
let v1 = {suit = Clubs;face = Two}
printfn "%A" v1.Color
红 黑色 Дляпродолжениянажмителюбуюклавишу。 。