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

荒凉一梦 提交于 2019-12-05 23:40:28

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.

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

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