F# 建模扑克牌
F# modeling playing cards
我正在尝试代表 standard playing cards in F#. My goal is to implement a clone of 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;
}
但是,一张牌的颜色可以从它的花色推断出来——所有的方块和红心都是红色的,所有的梅花和黑桃都是黑色的。西装不能仅从颜色来确定。也许这样的事情是合适的:
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;
}
但这似乎不对,因为这允许不正确的组合,例如黑心红桃。
我的问题是:
- 考虑到 Color 依赖于 Suit,处理 Suit 和 Color 最惯用的方法是什么?
- 是否应该明确表示颜色的概念?理论上可以将所有出现的颜色替换为与方块或红心(红色)和梅花或黑桃(黑色)匹配的图案。
由于 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"
您可以添加录音方式:
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
红色
黑色的
按任意键继续。 . .
我正在尝试代表 standard playing cards in F#. My goal is to implement a clone of 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;
}
但是,一张牌的颜色可以从它的花色推断出来——所有的方块和红心都是红色的,所有的梅花和黑桃都是黑色的。西装不能仅从颜色来确定。也许这样的事情是合适的:
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;
}
但这似乎不对,因为这允许不正确的组合,例如黑心红桃。
我的问题是:
- 考虑到 Color 依赖于 Suit,处理 Suit 和 Color 最惯用的方法是什么?
- 是否应该明确表示颜色的概念?理论上可以将所有出现的颜色替换为与方块或红心(红色)和梅花或黑桃(黑色)匹配的图案。
由于 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"
您可以添加录音方式:
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
红色 黑色的 按任意键继续。 . .