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

4
如何在具有静态解析类型参数的 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这一行遇到了以下错误:

此成员、函数或值声明可能不能声明为“inline”

为什么会出现这种情况?是因为Equals是一个覆盖吗?如果是这种情况,是否有任何方法来实现自定义相等性,或者我必须使用IEqualityComparer吗?

1个回答

4
为什么会这样?是因为Equals是一个覆盖方法吗?
是的,确实如此。类中的inline方法并不是类的真正方法。相反,对该方法的每次调用都将被解释为其实现(与C++非常相似)。由于您要覆盖的Equals方法是一个真正的方法(来自Object类),所以无法将其设置为inline
那如果是这样,有没有任何方法来实现自定义的相等性呢?
您可以将具体的乘法运算从类型中提取出来,这样您就不必为Equals方法使用inline了:
[<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

需要使用 #nowarn "1125" 吗?(泛型类型 'Frac' 的实例化缺失,无法从该成员的参数或返回类型中推断出。在访问此类型时,请考虑提供类型实例化,例如 'Frac<_>'。) - kaefer
是的,我忽略了那个警告。顺便说一下,还有一个警告,建议考虑实现GetHashCode方法,以便该类型可以与哈希相关的数据结构一起使用。 - Nghia Bui

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接