2017-01-23 39 views
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

你是完全控制你的类型还是他们的第三方?如果前者然后可能会做[像这样](https://ideone.com/Slqg4F)而不是? – ildjarn

+1

没有办法做到这一点,而这实际上表明你的类型没有足够好地反映你的域名。 –

回答

4

这个怎么样?

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

但说实话 - 我同意上述陀。你可能应该重新考虑你的类型。