How to properly overload global (+) and (*) without breaking support for other types

匆匆过客 提交于 2019-12-22 09:29:31

问题


I have imported a vector math library, and would like to add my own (*) and (+) operators while preserving the existing operators for basic int and float.

I have tried the following:

let inline (*) (x : float) (y : Vector) = y.Multiply(x)
let inline (*) (x : Vector) (y : float) = x.Multiply(y)
let inline (+) (x : Vector) (y : Vector) = x.Add(y)

Which has two problems:

  1. It seems to remove int + int and int * int, and
  2. The 2nd line (which is intended to complete commutativity) does not compile because it is a "duplicate definition".

How can I go about defining some commutative operators on my imported Vector type while also not losing these operations on ints and floats?

(I want to be able to write generic code elsewhere using * and +, without having to specify float/Vector/int type constraints).


回答1:


If you are able to modify source code of the library, it's simpler to add a few overloads via type extensions:

type Vector with
    static member (*) (x : Vector) (y : float) = x.Multiply(y)
    static member (+) (x : Vector) (y : Vector) = x.Add(y)

However, if the first operand has a primitive type (e.g your first example), overloading resolution doesn't work any more.

At any rate, you can exploit member overloading and propagate constraints to an inline function:

type VectorOverloadsMult =
    | VectorOverloadsMult
    static member (?<-) (VectorOverloadsMult, x: float, y: Vector) = y.Multiply(x)
    static member (?<-) (VectorOverloadsMult, x: Vector, y: float) = x.Multiply(y)     
    static member inline (?<-) (VectorOverloadsMult, x, y) = x * y

let inline (*) x y = (?<-) VectorOverloadsMult x y

This works for existing types with (*) since we preserve them in the last static member. You can do the same for (+) operator.

let v: Vector = ... // Declare a Vector value
let a = 2.0 * v
let b = v * 2.0
let c = 2 * 3
let d = 2.0 * 3.0

This technique works even when you cannot modify the Vector type.




回答2:


You need to define the operators inside your type - i.e.

type Vector = 
    ....
    static member (+) (x : Vector) (y : Vector) = x.Add(y)

etc.

Then all will work as you expect



来源:https://stackoverflow.com/questions/15858474/how-to-properly-overload-global-and-without-breaking-support-for-other-t

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