2017-01-23 11 views
3

Если у меня есть дискриминационный союз с совместными несколькими значений ребенка (Apple и MoreApples оба имеют типа 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

Вы управляете своими типами или являетесь третьим лицом? Если первое, возможно, сделает что-то вроде [this] (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" 

Но если честно - я согласен с Федором выше. Вероятно, вы должны переосмыслить свои типы.