F#造型扑克牌

the*_*guy 6 f# playing-cards

我想在F#中代表标准扑克牌.我的目标是实现一个微软纸牌(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
Run Code Online (Sandbox Code Playgroud)

卡的记录类型:

type Card = {
    suit: Suit;
    face: Face;
    color: Color;
}
Run Code Online (Sandbox Code Playgroud)

但是,卡片的颜色可以从它的套装中推断出来 - 所有钻石和红心都是红色的,所有的俱乐部和黑桃都是黑色的.不能仅从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;
}
Run Code Online (Sandbox Code Playgroud)

但这似乎不对,因为这允许不正确的组合,例如Black Hearts和Red Spades.

我的问题是:

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

Mar*_*ann 16

既然Color总是可以推断出来Suit,那就没有理由明确地对它进行建模; 你想让非法国家无法代表.

您仍然可以从模型中获得良好的编程体验,并使用活动模式有一种很好的颜色建模方法:

type Suit =
    | Diamonds
    | Hearts
    | Clubs
    | Spades

let (|Red|Black|) suit =
    match suit with
    | Diamonds | Hearts -> Red
    | Clubs | Spades -> Black
Run Code Online (Sandbox Code Playgroud)

这将使您能够模式匹配Suit,就像这个愚蠢的例子:

let printColor card =
    match card.Suit with
    | Red -> "Red"
    | Black -> "Black"
Run Code Online (Sandbox Code Playgroud)

FSI的用法示例:

> printColor { Suit = Spades; Face = Ace };;
val it : string = "Black"
> printColor { Suit = Diamonds; Face = King };;
val it : string = "Red"
Run Code Online (Sandbox Code Playgroud)