有没有办法按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
如何以通用方式实现compareCases
功能?
即。像下面这样的东西,但更通用(反射是可以的):
let compareCases a b =
match a with
| MyString(_) -> match b with | MyString(_) -> true | _ -> false
| MyInt(_) -> match b with | MyInt(_) -> true | _ -> false
答案 0 :(得分:5)
使用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)
答案 1 :(得分:3)
首先,您可以像这样改进您的示例:
let compare = function
| MyString _, MyString _, | MyInt _, MyInt _ -> true
| _ -> false
但这是最好的方式(反复最少!):
let compare a b = a.GetType () = b.GetType ()
答案 2 :(得分:0)
这应该可以解决问题
open Microsoft.FSharp.Reflection
type MyUnion =
| MyString of string
| MyInt of int
let x = MyString("hello")
let y = MyString("bye")
let z = MyInt(25)
let compareCases a b =
FSharpValue.GetUnionFields (a, a.GetType()) |> fst
= (FSharpValue.GetUnionFields (b, b.GetType()) |> fst)
但是,为了对这些值做任何事情,你仍然需要模式匹配,所以我不太明白这一点,说实话。
答案 3 :(得分:0)
let compareCases (a : MyUnion) (b : MyUnion) =
a.GetType().Name = b.GetType().Name