0

我有一个有区别的联盟,我希望使用像它这样的内置运算符> < compare max

[<CustomComparison>]
type SymbolType = 
    | A
    | B
    | C
    | D

    interface IComparable<SymbolType> with
        member x.CompareTo y =
            match x, y with
            | A, A-> 0
            | A, _ -> 1
            | _, A-> -1
            | _, _ -> 0

我知道我可以使用IComparable,但是我必须进行null检查,更糟糕的是我必须像(SymbolType) y我认为的那样进行投射,这会很耗时。

4

3 回答 3

3

已经可以在类型上使用标准比较运算符。内置实现使用各个案例的声明顺序,因此:

type SymbolType =  A | B | C | D 

// Behavior of built-in comparison
A < B   = true
D <= C  = false
max B D = D

这看起来很脆弱,所以也许它不是最好的依靠。如果您有不包含其他值的案例,您可以使用枚举而不是有区别的联合并定义您希望的排序:

type SymbolType =  
  | A = 1
  | B = 2
  | C = 4
  | D = 3

// The order is now defined by your code
SymbolType.C < SymbolType.D = false
于 2012-10-05T13:41:44.983 回答
1

您可以使用瘦包装器实现所需的方法:

[<CustomComparison>] 
[<CustomEquality>] 
type SymbolType = 
    | A
    | B
    | C
    | D
    override x.Equals y =
       match y with
       | :? SymbolType as t -> (((x :> IComparable<_>).CompareTo) t)=0
       | _ -> false
    interface IComparable with
        member x.CompareTo y =
            match y with
            | :? SymbolType as t -> ((x :> IComparable<_>).CompareTo) t
            | _ -> failwith "bad comparison"
    interface IComparable<SymbolType> with
        member x.CompareTo y =
            match x, y with
            | A, A-> 0
            | A, _ -> 1
            | _, A-> -1
            | _, _ -> 0

这种方式确实避免了任何重复输入。

于 2012-10-05T11:11:48.410 回答
0

在 CLR 上,运算符是静态函数,因此您不能在接口中定义它们。但是,如果您将接口用作泛型函数的类型参数的约束,也可以避免装箱。

int Compare<T>(T lhs, T rhs) where T : IComparable<T>
{
  return lhs.CompareTo(rhs) // no boxing
}

抱歉,我对 F# 不熟悉,所以我用 C# 编写了示例。

于 2012-10-05T11:18:44.310 回答