【问题标题】:Match on child discriminated union匹配受歧视的儿童工会
【发布时间】:2017-06-08 00:04:06
【问题描述】:

如果我有一个有多个值共享一个孩子的可区分联合(AppleMoreApples 都具有Apple 类型)...

type Apples =
  | GrannySmith
  | Gala

type Fruit =
  | Apple of Apples
  | MoreApples of Apples
  | Banana

let speakFruit = function
  | Apple GrannySmith 
  | MoreApples GrannySmith -> "granny smith"
  | Apple Gala 
  | MoreApples Gala -> "gala"
  | Banana -> "banana"

有没有办法在子联合上进行匹配以消除重复? - 类似:

let speakFruit2 = function
  | _ GrannySmith -> "granny smith"
  | _ Gala -> "gala"
  | Banana -> "banana"

【问题讨论】:

  • 您是完全控制您的类型还是他们是第 3 方?如果是前者,那么可能会做类似this 的事情吗?
  • 没有办法做到这一点,这实际上表明您的类型不能很好地反映您的域。

标签: f# discriminated-union


【解决方案1】:

这个怎么样?

let speakFruit = function
| Apple x | MoreApples x -> 
    match x with
    | GrannySmith -> "Granny Smith"
    | Gala -> "gala"
| Banana -> "banana"

【讨论】:

    【解决方案2】:

    我认为使用单一模式没有很好的方法,但是您可以定义一个活动模式,它可以让您从另一种视角看待两种苹果合并的数据:

    let (|AnyApple|Banana|) = function
      | Apple a | MoreApples a -> AnyApple a
      | Banana -> Banana 
    

    这隐藏了标准的Banana 定义 - 您可能应该使用另一个名称以避免混淆,但其余部分保持不变。现在您可以使用AnyApple 进行模式匹配:

    let speakFruit = function
      | AnyApple GrannySmith -> "granny smith"
      | AnyApple Gala -> "gala"
      | Banana -> "banana"
    

    【讨论】:

      【解决方案3】:

      部分活动模式也可以是一个解决方案

      let (|IsKind|_|) kind z =
          match z with
          | Apple x | MoreApples x -> if (kind = x) then Some true else None
          | _ -> None
      
      let speakFruit x = 
          match x with
          | IsKind GrannySmith z -> "Granny Smith"
          | IsKind Gala z -> "Gala"
          | Banana -> "banana"
          | _ -> "something else"
      

      但老实说 - 我同意上面的 Fyodor。您可能应该重新考虑您的类型。

      【讨论】:

        猜你喜欢
        • 2011-11-17
        • 1970-01-01
        • 2020-05-30
        • 1970-01-01
        • 2023-02-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多