2013-05-22 2 views
3

Я пытаюсь переопределить (=), чтобы иметь возможность сравнивать мой новый тип с int. Я хочу, чтобы достичь чего-то озеро это:F # op_Equality разные типы

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 Т - не получилось, слишком

Мне было интересно, возможно ли работать оператор (=) с двумя разными типами?

+2

ПРИМЕЧАНИЕ: Это ** не ** дубликат предыдущего вопроса. Здесь ОП спрашивает об определении равенства между двумя разными типами (предыдущий вопрос задает два значения одного и того же типа). –

ответ

2

Оператор = предполагает, что оба аргумента имеют один и тот же тип, поэтому я думаю, что нет возможности добавить перегрузку, которая работает на разных типах. Я думаю, что разумной альтернативы можно было бы определить пару операторов .= и =. (аналогичные операторы, например, .* и *. часто используются для скалярного умножения скаляра на левой и правой, соответственно):

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, компилятор дает вам предупреждение о том, что это обычно не рекомендуется). Во всяком случае, это может быть сделано с помощью 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 

Может быть, вы могли бы определить свой собственный оператор, используя метод, описанный в последней части ответа, но не скрывает = и вместо того, чтобы называть его по-разному. Затем вы можете обрабатывать перегрузки (а также стандартные типы), но вы не скрывали бы стандартное определение.

Смежные вопросы