2017-01-23 41 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" 

但說實話 - 我同意上述陀。你可能應該重新考慮你的類型。