【问题标题】:F# Pattern Matching Nested Discriminated UnionsF# 模式匹配嵌套的可区分联合
【发布时间】:2018-02-03 20:27:23
【问题描述】:

我有一个嵌套的可区分联合代表一副扑克牌:

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
 ...

非常感谢。

【问题讨论】:

    标签: f# pattern-matching


    【解决方案1】:

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

    type Rank =
      | Seven
      | Eight
      | Nine
      | Ten
      | Jack
      | Queen
      | King
      | Ace
    
    type Suit =
      | Heart
      | Diamond
      | Spade
      | Club
    
    type Card = { suit: Suit; rank: Rank }
    
    let getValue (card:Card) = 
       match card.rank with
       | Seven | Eight | Nine -> 0
       | Ten -> 10
       ...
    

    【讨论】:

    • @dlkmp - 这是正确的答案。 Chad Gilbert 的回答有效,但只要你有一个不正确的数据模型,你就会不断遇到更多这样的问题。让您的数据模型正确,其余代码将更自然地流动。
    • 我同意我的示例中的数据模型不是很聪明,但基本问题集中在模式匹配嵌套的可区分联合上。这无法像我希望的那样解决,而 Chad Gilbert 的回答就是针对这个问题,所以我将把它作为正确的答案。不过,我会改变我的数据模型。
    【解决方案2】:

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

    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
      ...
    

    【讨论】:

      【解决方案3】:

      这是另一种方式:

      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
      

      【讨论】:

      • y when y = Ten 是超级冗余的,仅相当于 Ten
      • @FyodorSoikin - 谢谢,我修好了。
      猜你喜欢
      • 2019-01-10
      • 1970-01-01
      • 1970-01-01
      • 2014-04-21
      • 2019-06-06
      • 2012-08-27
      • 2018-11-24
      • 2014-05-07
      • 1970-01-01
      相关资源
      最近更新 更多