Pregunta

I'm trying to override (=) to be able to compare my newly defined type with int. I want to achieve something lake this:

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

I can easily make it work in C# but cannot do this in F#

I've also tried

  • to create static member (+), but it gives me a warning and does not work
  • to add CustomEqualityAttribute to T - did not work, too

I was wondering if it is possible to make a (=) operator work with two different types at all?

¿Fue útil?

Solución

The standard = operator assumes that both of the arguments have the same type, so I think there is no way to add an overload that works on different types. I think a sensible alternative might be to define a pair of operators .= and =. (similar operators e.g. .* and *. are often used for scalar multiplication with scalar on the left and right, respectively):

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

But perhaps it is better to just ask the user to write a.N = y explicitly when they want to compare two values of different types (because, strictly speaking, two values of the same type can never be equal - they are not even of the same type!)

If you really wanted to, you could re-define the = operator, but I would not recommend that (and, when you define the operator (=) using let, the compiler gives you a warning saying that this is normally not recommended). Anyway, it could be done using a trick described e.g. here:

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

Perhaps you could define your own operator using the method described in the latter part of the answer, but do not hide = and instead call it differently. Then you could handle overloads (as well as standard types) but you would not hide the standard definition.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top