使用静态解析的类型参数自定义类型的相等性

时间:2019-05-13 15:11:03

标签: generics types f# inline equality

如何在带有静态解析类型参数的F#类型中实现自定义相等方法?

我尝试过这种方式:

[<CustomEqualityAttribute>]
type Fraction< ^a when ^a: equality and ^a : (static member (*): ^a * ^a -> ^a) > (nominator: ^a, denominator: ^a) =
    member inline this.Nominator = nominator
    member inline this.Denominator = denominator

    member inline this.IsEqualTo(other: Fraction< ^a >) = this.Nominator * other.Denominator = other.Nominator * this.Denominator

    override inline this.Equals(other: obj) =
        match obj with
        | :? Fraction< ^a > as f -> this.IsEqualTo(f)
        | _ -> false

我在this.Equals行上收到以下错误:

  

此成员,函数或值声明不得声明为“内联”

那是为什么?是因为Equals是替代项吗?如果是这样,有什么办法可以实现自定义相等性,还是我不得不使用IEqualityComparer

1 个答案:

答案 0 :(得分:3)

  

那是为什么?是因为Equals是优先选项吗?

是的。类的inline方法不是该类的 actual 方法。相反,在某个地方对该方法的每次调用都将被解释为其实现(非常类似于C ++)。由于您要覆盖Equals类中的实际方法Object,因此无法将其设为inline

  

如果是这样,有什么办法可以实现自定义相等性?

您可以从类型中提取具体乘法,因此不会强制inline方法使用Equals

[<CustomEquality; NoComparison>]
type Frac<'T when 'T : equality> = private {
    nominator : 'T
    denominator : 'T
    mult : 'T -> 'T -> 'T
} with
    member x.Nominator = x.nominator
    member x.Denominator = x.denominator
    override x.Equals other =
        match other with
        | :? Frac<'T> as o -> 
            let ( * ) = x.mult in x.nominator * o.denominator = o.nominator * x.denominator
        | _ -> false
    static member inline Create x y = { nominator = x; denominator = y; mult = ( * ) }
// Test
Frac.Create 1 2 = Frac.Create 3 6 // true
Frac.Create 1.0 2.0 = Frac.Create 3.0 7.0 // false
Frac.Create 1 2 = Frac.Create 3.0 6.0 // compile error