如何在F#中为一个受歧视的联盟覆盖GetHashCode和CompareTo?

use*_*861 3 f# icomparable gethashcode discriminated-union

我有一个简单的F#区分联合,它结合了bool,一个字符串和一个浮点数.我想覆盖此联合的Object.Equals(arg),以便在检查浮点相等时我可以放入epsilon来解决精度错误.编译器抱怨说如果我覆盖this.Equals(arg),我也应该重写this.GetHashCode()和this.CompareTo(arg).对于这些覆盖,我没有计划特殊功能,所以我只想调用这些方法的默认版本.在我的实现中,我有三次调用GetHashCode,并且对我所区分的并集中的每种类型调用CompareTo三次:每种类型一次.

有没有办法只用一次GetHashCode调用来编码GetHashCode覆盖?CompareTo的问题是什么?我所区分的联盟中的所有类型都实现了ICompareable.

[<CustomEquality;CustomComparison>]
type MyType =
    | Bool of bool
    | Str of string
    | Float of float

    override this.Equals(arg) =
        let epsilon = 0.1
        match arg with
        | :? MyType as other ->
            match this, other with
            | Bool(a), Bool(b) -> a = b
            | Str(a), Str(b) -> a = b
            | Float(a), Float(b) -> Math.Abs(a - b) < epsilon
            | _ -> false
        | _ -> false

    override this.GetHashCode() =
        match this with
        // Three calls to GetHashCode.  I'd like only one
        | Bool(a) -> a.GetHashCode()
        | Str(a) -> a.GetHashCode()
        | Float(a) -> a.GetHashCode()
        | _ -> 0

    interface System.IComparable with
        member this.CompareTo arg =
            match arg with
                | :? MyType as other ->
                    match this, other with
                    // Three calls to CompareTo.  I'd like only one
                    | Bool(a), Bool(b) -> a.CompareTo(b)
                    | Str(a), Str(b) -> a.CompareTo(b)
                    | Float(a), Float(b) -> a.CompareTo(b)
                    | _ -> 0
                | _ -> 0
Run Code Online (Sandbox Code Playgroud)

Tom*_*cek 5

您可以定义一个帮助器属性,该属性将DU的内容提取为obj:

member this.Value = 
  match this with
  | Bool(b) -> box b
  | Str(s) -> box s
  | Float(f) -> box f
Run Code Online (Sandbox Code Playgroud)

然后你可以GetHashCode通过获取值(它涉及一些装箱,因此它会有点慢)并调用GetHashCode返回的对象来实现:

override this.GetHashCode() =
  this.Value.GetHashCode()
Run Code Online (Sandbox Code Playgroud)

  • 这回答了提出的问题,但是不可取的; 看我对这个问题的评论. (2认同)