F#造型扑克牌

时间:2015-03-12 04:04:32

标签: f# playing-cards

我想在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;
}

但这似乎并不合适,因为这样可以实现不正确的组合,例如:黑心和红锹。

我的问题是:

  1. 考虑到Color依赖于Suit?
  2. ,最适合处理套装和颜色的方法是什么?
  3. Color的概念是否应该明确表示?理论上,人们可以用针对钻石或心形(红色)和俱乐部或黑桃(黑色)的模式匹配替换所有出现的颜色。

2 个答案:

答案 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

红 黑色 Дляпродолжениянажмителюбуюклавишу。 。