Is there a way to compare discriminated unions by their case-identifiers in F#?
type MyUnion = | MyString of string | MyInt of int let x = MyString("hello") let y = MyString("bye") let z = MyInt(25) let compareCases a b = // compareCases x y = true // compareCases x z = false // compareCases y z = false
How do I implement
compareCases function in a generic way?
I.e. something like the following, but more generic (reflection is ok):
let compareCases a b = match a with | MyString(_) -> match b with | MyString(_) -> true | _ -> false | MyInt(_) -> match b with | MyInt(_) -> true | _ -> false
The problem with using GetType() is that it fails if you have 2 'dataless' cases.
Here is one way to do it: (Edited because the previous UnionTagReader was not being cached)
type MyDU = | Case1 | Case2 | Case3 of int | Case4 of int type TagReader<'T>() = let tr = assert FSharpType.IsUnion(typeof<'T>) FSharpValue.PreComputeUnionTagReader(typeof<'T>, System.Reflection.BindingFlags.Public) member this.compareCase (x:'T) (y:'T) = (tr x) = (tr y) let tr = TagReader<MyDU>() let c1 = Case1 let c2 = Case2 let c3 = Case3(0) let c3' = Case3(1) let c4 = Case4(0) assert (c1.GetType() = c2.GetType() ) //this is why you can not use GetType() assert tr.compareCase c1 c1 assert not (tr.compareCase c1 c2) assert tr.compareCase c3 c3' assert not (tr.compareCase c3 c4)