Custom equality of types with statically resolved type parameters

笑着哭i 提交于 2020-02-21 23:57:33

问题


How to implement custom equality methods in F# types with statically resolved type parameters?

I've tried doing it this way:

[<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

I get the following error on the this.Equals line:

This member, function or value declaration may not be declared 'inline'

Why is that? Is it because the Equals is an override? If that's the case, is there any way at all to implement the custom equality or am I forced to use an IEqualityComparer?


回答1:


Why is that? Is it because the Equals is an override?

Yes, it is. An inline method of a class is not an actual method of the class. Rather, every call to that method at somewhere will be interpreted as its implementation (very similar to C++). Since you are overriding the Equals method which is an actual method (from the Object class), you cannot make it inline.

If that's the case, is there any way at all to implement the custom equality?

You can extract the concrete multiplication out of the type, so you won't be forced to use inline for the Equals method:

[<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


来源:https://stackoverflow.com/questions/56115210/custom-equality-of-types-with-statically-resolved-type-parameters

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!