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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With