If there’s another way to achieve what I’m trying to do below, please let me know. Suppose I have the following sample code
type FooBar =
| Foo
| Bar
let foobars = [Bar;Foo;Bar]
let isFoo item =
match item with
| Foo _ -> true
| _ -> false
foobars |> Seq.filter isFoo
I want to write a generic/higher-order version of isFoo that allows me to filter my list based on all other types of the discriminated union (Bar in this case).
Something like the following, where ‘a can be either Foo or Bar
let is<'a> item =
match item with
| a _ -> true
| _ -> false
However, this attempt yields the following error:
error FS0039: The pattern discriminator ‘a’ is not defined
If you just want to filter a list, then the easiest option is to use
functionto write standard pattern matching:If you wanted to write some more complicated generic function that checks for a case and then does something else, then the easiest option (that will work in general) is to take a predicate that returns
trueorfalse:In your specific example, you have a discriminated union where none of the cases has any parameters. This is probably an unrealistic simplification, but if you only care about discriminated unions without parameters, then you can just use the cases as values and compare them:
This last method will not work if you have more complicated discriminated union where some cases have parameters, so it is probably not very useful. For example, if you have a list of option values:
You could do various tricks using Reflection (to check for cases with a specified name) and you could also use F# quotations to get a bit nicer and safer syntax, but I do not think that’s worth it, because using pattern matching using
functiongives you quite clear code.EDIT – Just out of curiosity, a solution that uses reflection (and is slow, not type safe and nobody should actually use it in practice unless you really know what you’re doing) could look like this:
It uses quotations to identify the union case, so you can then write something like this: