Is it possible to pass discriminated union tags as arguments?

discriminated-union, f#, pattern-matching

Solution

Discriminated unions works best if there is no semantic overlap between the cases.

In your example, each case contains the same component with the same meaning, a `string` indicating "the name of the animal". But that's a semantic overlap! The discriminating union will then force you to make distinctions you don't want to: You don't want to be forced to discriminate between the "name of a pig" and the "name of a cow"; you just want to think of "the name of an animal".

Let's make a type that fits better:

type Animal = Pig  | Cow  | Fish
type Pet = Animal * string

let animals = [(Pig, "Mike"); (Fish, "Eve"); (Pig, "Romeo")

With that type, filtering out non-`Pig`s is a one-liner:

animals |> List.filter (fst >> (=) Pig) 

If not every animal has a name, use an option type:

type Pet = Animal * string option

You would use a discriminated union for your animals if you knew that, say, every `Pig` has a name, but no `Fish` does: those cases have no overlap.

Problem

Is it possible to pass the type of a discriminated union tag to another function so it can use it for pattern matching? Non working example of what I mean: ``` type Animal = Pig of string | Cow of string | Fish of string let animals = [Pig "Mike"; Pig "Sarah"; Fish "Eve"; Cow "Laura"; Pig "John"] let rec filterAnimals animalType animals = if animals = [] then [] else let rest = filterAnimals animalType (List.tail animals) match List.head animals with |animalType animal -> animal::rest // <- this doesn't work |_ -> rest printfn "%A" (filterAnimals Pig animals) ```

Original source