Wildcard for type when matching discriminated unions
-
21-12-2019 - |
Question
In the following real world example I do 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 efficient match, so I don't need to check each clothing case? Something like this:
let matchPerson person=
match person with
| Person(name, _ (Ugly,_) ) -> printfn "%s wears ugly stuff." name
| _ -> ()
Of course, this is not correct syntax. But how can I achieve such an effect?
Solution
That's not straightforward, you can use reflection, but the problem is that your discriminated union needs some redesign, because if you know there will always be a ClothingProperties 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
| _ -> ()
A related issue is described here Is it possible to pass discriminated union tags as arguments?
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow