如何在不中断对其他类型的支持的情况下适当地重载全局(+)和(*) [英] How to properly overload global (+) and (*) without breaking support for other types
问题描述
我已经导入了向量数学库,并希望添加自己的(*)和(+)运算符,同时保留现有的基本int和float运算符.
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.
我尝试了以下操作:
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)
有两个问题:
- 似乎删除了
int + int
和int * int
以及 - 第二行(旨在实现可交换性)未编译,因为它是重复定义".
- It seems to remove
int + int
andint * int
, and - The 2nd line (which is intended to complete commutativity) does not compile because it is a "duplicate definition".
如何在导入的Vector类型上定义一些可交换运算符,同时又不丢失int和float上的这些运算符?
How can I go about defining some commutative operators on my imported Vector type while also not losing these operations on ints and floats?
(我希望能够使用*和+在其他地方编写通用代码,而不必指定float/Vector/int类型约束).
(I want to be able to write generic code elsewhere using * and +, without having to specify float/Vector/int type constraints).
推荐答案
如果您能够修改库的源代码,则通过类型扩展添加一些重载会更简单:
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
即使您无法修改Vector
类型,该技术也可以使用.
This technique works even when you cannot modify the Vector
type.
这篇关于如何在不中断对其他类型的支持的情况下适当地重载全局(+)和(*)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!