F#模式匹配嵌套歧视联盟

时间:2017-08-25 18:14:19

标签: f# pattern-matching

我有一个代表一副扑克牌的嵌套歧视联盟:

type Symbol =
| Seven
| Eight
| Nine
| Ten
| Jack
| Queen
| King
| Ace

type Card =
| Heart of Symbol
| Diamond of Symbol
| Spade of Symbol
| Club of Symbol

现在我想编写一个返回给定卡片值的函数,在我的情况下,它独立于卡片套装:

let GetValue (card : Card) =
  match card with
  | Heart(Seven) -> 0
  | Diamond(Seven) -> 0
  | Spade(Seven) -> 0
  | Club(Seven) -> 0
  ...

这写起来显然很乏味。有没有办法做这样的事情

let GetValue (card : Card) =
  match card with
  | _(Seven) | _(Eight) | _(Nine) -> 0
  | _(Ten) -> 10
 ...

非常感谢。

3 个答案:

答案 0 :(得分:9)

您正在对数据建模不正确。由于总甲板是套装和等级的完整笛卡尔积,因此将“包裹”等级划分为西装是没有意义的。这两者应该是卡片的独立,同等重要的属性:

{{1}}

答案 1 :(得分:5)

您将无法以这种方式绕过构造函数匹配,但您可以通过创建一个从卡中拉出符号的函数来删除一些单调乏味:

let symbol card =
  match card with
  | Heart(s) -> s
  | Diamond(s) -> s
  | Spade(s) -> s
  | Club(s) -> s

let GetValue (card : Card) =
  match symbol card with
  | Seven | Eight | Nine -> 0
  | Ten -> 10
  ...

答案 2 :(得分:1)

这是另一种方式:

let set789 = [Seven; Eight; Nine] |> Set.ofList
let cardValue x =
    match x with
    | y when Set.contains y set789 -> 0
    | Ten   ->  1
    | Jack  ->  2
    | Queen ->  3
    | King  ->  4
    | Ace   ->  5
    | _     -> -1

let GetValue (card : Card) =
  match card with
  | Club(x) | Spade(x) | Diamond(x) | Heart(x) -> cardValue x