匹配子区分联合类型

3
如果我有一个具有共享子项的联合类型(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"

1
你是否完全掌控了你的类型,还是它们是来自第三方?如果是前者,那么或许可以尝试类似这样的做法? - ildjarn
1
没有办法做到这一点,实际上这表明您的类型不足以充分反映您的领域。 - Fyodor Soikin
3个回答

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"

4
这个怎么样?
let speakFruit = function
| Apple x | MoreApples x -> 
    match x with
    | GrannySmith -> "Granny Smith"
    | Gala -> "gala"
| Banana -> "banana"

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的观点。你可能需要重新考虑你的类型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接