f# 中可区分联合的内置比较

Sør*_*ois 5 f# compare icomparable compareto discriminated-union

在回答这个问题compare时,我发现了受歧视工会的以下行为。

type T = A | B | C | D 
compare A B   (* val it : int = -1 *)
compare A C   (* val it : int = -2 *)
compare A D   (* val it : int = -3 *)
Run Code Online (Sandbox Code Playgroud)

我对此感到惊讶。

我可以compare像这样测量构造函数之间的“距离”吗?

规范(第 154 页)关于生成的compareTo

如果 T 是联合类型,则首先对两个值的联合案例的索引调用 Microsoft.FSharp.Core.Operators.compare,然后对联合案例携带的数据的 x 和 y 的每个相应字段对调用。返回第一个非零结果。

由此,我希望compare类型T总是给出其中之一,-1,0,1因为这就是compare数字类型的行为方式。(正确的?)

Tom*_*cek 4

规范中的引用说生成的比较将首先比较标签(本质上是构造函数的索引),但我不确定这是否为您提供任何有用的信息 - 因为如果联合带有一些值,您将不知道这个数字是构造函数之间的距离,还是包含值的比较结果。例如:

type Tricky() = 
  interface System.IComparable with
    override x.CompareTo(b) = -2

type DU = 
 | A of Tricky
 | B 
 | C

// Returns -2 because of the distance between constructors
compare (A (Tricky())) C
// Returns -2 because of the comparison on `Tricky` objects
compare (A (Tricky())) (A(Tricky()))
Run Code Online (Sandbox Code Playgroud)

如果您想依靠获取构造函数之间距离的能力,那么使用枚举可能更安全:

type DU = 
 | A = 1
 | B = 2 
 | C = 3
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用 将值转换为整数来获取距离(int DU.A) - (int DU.C)