Just for completeness, I'll list this solution.
If you quoted your input, you'd be able to reason about the names of the tags:
open Microsoft.FSharp.Quotations
type Animal = Pig of string | Cow of string | Fish of string
let isAnimal (animalType : Expr) (animal : Expr) =
match animal with
| NewUnionCase(at, _) ->
match animalType with
| Lambda (_, NewUnionCase (aatt, _)) -> aatt.Name = at.Name
| _ -> false
| _ -> false
let animal = <@ Pig "Mike" @>
isAnimal <@ Pig @> animal // True
isAnimal <@ Cow @> animal // False
This is admittedly quite verbose though, and it would become even more so if you wanted to quote a list instead of a single value.
A slightly different version, where we quote only the animal type, would let you easily filter lists of animals, as you need (at the price of some questionable comparison of strings):
open Microsoft.FSharp.Quotations
type Animal = Pig of string | Cow of string | Fish of string
let isAnimal (animalType : Expr) animal =
match animalType with
| Lambda (_, NewUnionCase (aatt, _)) -> animal.ToString().EndsWith(aatt.Name)
| _ -> false
let animal = Pig "Mike" // No quote now, so we can process Animal lists easily
isAnimal <@ Pig @> animal // True
isAnimal <@ Cow @> animal // False
let animals = [Pig "Mike"; Pig "Sarah"; Fish "Eve"; Cow "Laura"; Pig "John"]
let pigs = animals |> List.filter (isAnimal <@ Pig @>)
The latter version is not really superior to passing the tag name as a string.