在 F# 中如何重载 "=" 和 "<>" 运算符

3
open System

type Point(X : float, Y : float) =
  class
    member public this.X : float = X
    member public this.Y : float = Y
    static member public Origin : Point = Point(0.0, 0.0)
  
    static member public (+) (P1 : Point, P2 : Point) : Point =
      Point(P1.X+P2.X, P1.Y+P2.Y)
    
    static member public (-) (P1 : Point, P2 : Point) : Point =
      Point(P1.X-P2.X, P1.Y-P2.Y)
    
    static member public op_Equality (P1 : Point, P2 : Point) : bool =
      P1.X = P2.X && P1.Y = P2.Y
      
    static member public op_Inequality (P1 : Point, P2 : Point) : bool =
        P1.X <> P2.X && P1.Y <> P2.Y
    
    override this.ToString() = 
      String.Format("({0}, {1})", X, Y)
  end

我试图重载“=”(等于运算符)和“<>”(不等于运算符),但是通过它们的符号重载相等和不相等运算符-“+”(加法运算符)和“-”(减法运算符)是不允许的。

当我尝试使用它们的符号“=”(等于运算符)和“<>”(不等于运算符)时,我得到了以下消息:

名称“(=)”不应用作成员名称。要为类型定义相等语义,请重写“Object.Equals”成员。如果定义供其他CLI语言使用的静态成员,则应改用名称“op_Equality”。

名称“(<>)”不应用作成员名称。要为类型定义相等语义,请重写“Object.Equals”成员。如果定义供其他CLI语言使用的静态成员,则应改用名称“op_Inquality”。

我按照第二个建议定义了这些运算符作为静态成员。从积极的一面看,没有错误。但是,在条件p1 = Point(1, 0)p2 = Point(1, 0)下,p1 = p2必须返回true(在我的程序中返回false),而p1 <> p2必须返回false(在我的程序中返回true)。

我是F#的新手,不知道如何修正此错误。有人能帮我吗?


1
遵循其他建议:实现Object.Equals。第二个建议明确表示它仅供其他.NET语言使用。 - Fyodor Soikin
1个回答

3

在F#中很少需要自己实现结构相等性。如果将Point定义为记录类型,它将默认实现结构相等性:

type Point =
    {
        X : float
        Y : float
    }

    static member public (+) (P1 : Point, P2 : Point) =
        { X = P1.X + P2.X; Y = P1.Y + P2.Y }
    
    static member public (-) (P1 : Point, P2 : Point) : Point =
        { X = P1.X - P2.X; Y = P1.Y - P2.Y }

测试代码:

let p1 = { X = 1.0; Y = 0.0 }
let p2 = { X = 1.0; Y = 0.0 }
(p1 = p2) |> printfn "%A"    // true
(p1 <> p2) |> printfn "%A"   // false

你还可以免费获得记录类型的漂亮打印输出,因此通常不需要覆盖 ToString 函数。
(p1 + p2) |> printfn "%A"   // {X = 2; Y = 0}

如果你将 Point 记录类型反编译为 C#,你就可以看到结构相等性是由 F# 编译器自动实现的:

public sealed class Point : IEquatable<Point>, IStructuralEquatable, IComparable<Point>, IComparable, IStructuralComparable
{
    ...
}

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