假设我有一个很大的歧视联盟类型:
type Thing =
| One of int
| Two of string
| Three of bool option
...
我有这个功能:
let comp a b = match a, b with
| One _, One _ -> true
| Two _, Two _ -> true
...
| _, _ -> false
有没有办法以更简洁的方式编写函数,不需要我列出每一个构造函数?
答案 0 :(得分:3)
基本上,这是不可能的。即使您可以获得值的构造函数,它们也不具有可比性,因为它们是函数。这里有一些样板文件,但你可以定义标签值和一个映射到标签的函数:
let thingCase thing =
match thing with
| One _ -> 1
| Two _ -> 2
| Three _ -> 3
let comp a b = thingCase a = thingCase b
这足够灵活,可以处理序列:
let compSeq things =
things
|> Seq.map thingCase
|> Seq.pairwise
|> Seq.forall (fun (a, b) -> a = b)
注意:您也可以使用反射进行此操作,但通常最好避免使用。
答案 1 :(得分:2)
我不太确定它在性能方面有多好,但可以使用FSharp.Reflection
执行此操作。
open FSharp.Reflection
type Thing =
| One of int
| Two of string
| Three of bool option
let tagOfThing = FSharpValue.PreComputeUnionTagReader(typeof<Thing>)
// val tagOfThing : obj -> int
let isSameThingCase (a: Thing) (b: Thing) =
tagOfThing a = tagOfThing b
使用:
> isSameThingCase (One 1) (One 2);;
val it : bool = true
> isSameThingCase (Two "test") (Three None);;
val it : bool = false