F#比较区分联合的案例标识符

Gro*_*ozz 4 .net reflection f# discriminated-union

有没有办法通过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
Run Code Online (Sandbox Code Playgroud)

如何compareCases以通用方式实现功能?

即如下所示,但更通用(反射是可以的):

let compareCases a b =
  match a with
  | MyString(_) -> match b with | MyString(_) -> true | _ -> false
  | MyInt(_) -> match b with | MyInt(_) -> true | _ -> false
Run Code Online (Sandbox Code Playgroud)

jyo*_*ung 6

使用GetType()的问题是,如果你有2个'无数据​​'的情况,它就会失败.

这是一种方法:(编辑因为之前的UnionTagReader没有被缓存)

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)
Run Code Online (Sandbox Code Playgroud)