3

我已经导入了一个向量数学库,并且想添加我自己的 (*) 和 (+) 运算符,同时保留基本 int 和 float 的现有运算符。

我尝试了以下方法:

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)

这有两个问题:

  1. 它似乎删除了int + intand int * int, and
  2. 第二行(旨在完成交换性)无法编译,因为它是“重复定义”。

如何在导入的 Vector 类型上定义一些交换运算符,同时又不会丢失对 int 和 float 的这些操作?

(我希望能够使用 * 和 + 在其他地方编写通用代码,而不必指定 float/Vector/int 类型约束)。

4

2 回答 2

10

如果您能够修改库的源代码,则通过类型扩展添加一些重载会更简单:

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

但是,如果第一个操作数具有原始类型(例如您的第一个示例),则重载解析不再起作用。

无论如何,您可以利用成员重载并将约束传播到内联函数:

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

这适用于现有类型,(*)因为我们将它们保存在最后一个静态成员中。您可以对操作员执行相同的(+)操作。

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

即使您无法修改Vector类型,此技术也有效。

于 2013-04-07T07:33:45.980 回答
3

您需要在类型中定义运算符 - 即

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

等等

然后一切都会如你所愿

于 2013-04-07T06:37:25.800 回答