Type wildcard when matching discriminatory unions

In the following real-world example, I make a match:

type Style = Nice | Cool | Ugly
type Color = Blue | Yellow | Orange | Grey | Cyan
type ClothingProperties = Style * Color

type Clothes =
| Jeans of ClothingProperties
| Pullover of ClothingProperties
| Shirt of ClothingProperties

type Person =
| Person of string * Clothes

let team = [Person("Jan", Jeans (Cool, Blue)); Person("Pete", Shirt (Nice, Cyan)); Person("Harry", Pullover (Ugly, Grey))]

let matchPerson person=
    match person with
    | Person(name,  Jeans(Ugly,_) ) -> printfn "%s wears ugly stuff." name
    | Person(name,  Pullover(Ugly,_) ) -> printfn "%s wears ugly stuff." name
    | Person(name,  Shirt(Ugly,_) ) -> printfn "%s wears ugly stuff." name
    | _ -> ()

List.iter(fun x->matchPerson x) team

Is there a way to create a more effective match, so I don’t need to check every case of clothes? Something like that:

let matchPerson person=
    match person with
    | Person(name,  _ (Ugly,_) ) -> printfn "%s wears ugly stuff." name
    | _ -> ()

Of course, this is the wrong syntax. But how can I achieve this effect?

+3
source share
1 answer

It's not easy, you can use reflection, but the problem is that your discriminatory union needs some redesign, because if you know that there will always be clothes, then you can change it to this:

type Style = Nice | Cool | Ugly
type Color = Blue | Yellow | Orange | Grey | Cyan
type ClothingProperties = Style * Color // or just use a tuple

type Clothe =
| Jeans 
| Pullover
| Shirt

type Clothes = Clothe *ClothingProperties
type Person =
| Person of string * Clothes

let matchPerson person=
    match person with
    | Person(name,  (_,(Ugly,_)) ) -> printfn "%s wears ugly stuff." name
    | _ -> ()

union ?

+5

Source: https://habr.com/ru/post/1544563/


All Articles