f# - 如何在不破坏对其他类型的支持的情况下正确重载全局 (+) 和 (*)

标签 f# operator-overloading

我已经导入了一个向量数学库,并希望添加我自己的 (*) 和 (+) 运算符,同时保留基本 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)

这有两个问题:
  • 好像删除了int + intint * int , 和
  • 第二行(旨在完成交换性)无法编译,因为它是“重复定义”。

  • 如何在导入的 Vector 类型上定义一些可交换运算符,同时又不丢失对整数和浮点数的这些操作?

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

    最佳答案

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

    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
    

    这适用于 (*) 的现有类型因为我们将它们保存在最后一个静态成员中。您可以对 (+) 执行相同操作运算符(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,此技术也能奏效。类型。

    关于f# - 如何在不破坏对其他类型的支持的情况下正确重载全局 (+) 和 (*),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15858474/

    相关文章:

    f# - 两个简单的 F# 问题

    c++ - 我的编译器在 C/C++、OCaml 和 F# 之间犹豫不决

    c++ - 链接 operator<< 和 operator++ 的问题

    c++ - 关于重载赋值运算符的困惑

    f# - 有没有更好的方法在 F#/OCaml 中编写交换函数?

    f# - 如何使用 websockets

    c++ - Qt序列化。 QDataStream & operator<< 用于基类 QPolygonF

    python - 猴子修补运算符重载在 Python2 与 Python3 中的行为不同

    reflection - 在 D 中透明地同步对象中的任意属性

    可区分联合的 F# 限制