3

我正在尝试覆盖 (=) 以便能够将我新定义的类型与 int 进行比较。我想实现一些湖这个:

type T = T with static member op_Equality (_ : T, c : int) = true

let b = T = 2 // Error: This expression was expected to
              // have type T but here has type int

我可以很容易地使它在 C# 中工作,但不能在 F# 中做到这一点

我也试过

  • 创建静态成员(+),但它给了我一个警告并且不起作用
  • 将 CustomEqualityAttribute 添加到 T - 也不起作用

我想知道是否可以让 (=) 运算符与两种不同的类型一起使用?

4

1 回答 1

2

标准=运算符假定两个参数具有相同的类型,所以我认为没有办法添加适用于不同类型的重载。我认为一个明智的选择可能是定义一对运算符.=and =.(类似的运算符,例如.**.通常用于标量乘法,标量分别位于左侧和右侧):

type Foo(n:int) = 
  member x.N = n
  static member (=.) (x:Foo, y:int) = x.N = y
  static member (.=) (y:Foo, x:int) = x.N = y

但是,当用户想要比较不同类型的两个值时,也许最好只要求用户a.N = y显式编写(因为严格来说,相同类型的两个值永远不可能相等——它们甚至不属于同一类型!)

如果您真的想要,您可以重新定义=运算符,但我不建议这样做(并且,当您使用 定义运算符时(=)let编译器会向您发出警告,指出通常不推荐这样做)。无论如何,可以使用这里描述的技巧来完成:

type Foo(n:int) =
  member x.N = n

// A type that contains all overloads of the `=` 
// operator that you want to support
type Equality = EQ with    
  static member (?<-) (_:Equality, x:int, y:int) = x = y
  static member (?<-) (_:Equality, x:float, y:float) = x = y
  static member (?<-) (_:Equality, x:Foo, y:int) = x.N = y

// This hides the standard equality operator and can 
// lead to all sorts of confusion! (Probably do not do this :-))
let inline (=) x y = (?<-) EQ x y

10 = 4
Foo(10) = 3

也许您可以使用答案后半部分中描述的方法定义自己的运算符,但不要隐藏=,而是以不同的方式调用它。然后您可以处理重载(以及标准类型),但您不会隐藏标准定义。

于 2013-05-22T15:24:47.173 回答