与儿童歧视联盟相匹配

时间:2017-01-23 13:00:19

标签: f# discriminated-union

如果我有一个有多个价值观的歧视联盟,分享一个孩子(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 个答案:

答案 0 :(得分:5)

我不认为使用单一模式有一种很好的方法可以做到这一点,但是您可以定义一个活动模式,它将为您提供合并两种苹果的数据的替代视角:

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"

答案 1 :(得分:4)

这个怎么样?

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

答案 2 :(得分:2)

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

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。你可能应该重新考虑你的类型。