【问题标题】:Multiple dispatch behavior for operator overloads运算符重载的多重分派行为
【发布时间】:2016-07-25 03:22:45
【问题描述】:

以下给出重复定义错误:

let (.*) (m1 : Matrix<float>) (m2 : Matrix<float>) =
    m1.Multiply(m2)

let (.*) (v1 : Vector<float>) (v2 : Vector<float>) =
    v1.DotProduct(v2)

有没有办法定义运算符重载,以便 F# 根据函数签名识别我尝试调用的函数?

例如 Julia 有这个非常有用的功能:

julia> methods(*)
# 138 methods for generic function "*":
*(x::Bool, y::Bool) at bool.jl:38
*{T<:Unsigned}(x::Bool, y::T<:Unsigned) at bool.jl:53
*(x::Bool, z::Complex{Bool}) at complex.jl:122
*(x::Bool, z::Complex{T<:Real}) at complex.jl:129
...

如果有一种方法可以在 F# 中复制类似的东西,那就太好了。

【问题讨论】:

  • F# 可以进行广泛的类型推断,并且不能很好地处理函数/运算符重载。您需要内联或将其放入类中。
  • 事实上你似乎不能在扩展成员中重载运算符...
  • 顺便说一句,我看了一下 Julia,它很好,但显然这是它的优势之一:'Julia 程序是围绕多个调度组织的;通过定义函数并为不同的参数类型组合重载它们,这也可以是用户定义的。 '

标签: f# operator-overloading math.net


【解决方案1】:

在这种特定情况下,* 已经超载。例如:

let m = matrix [[ 1.0; 4.0; 7.0 ]
                [ 2.0; 5.0; 8.0 ]
                [ 3.0; 6.0; 9.0 ]]
let v = vector [ 10.0; 20.0; 30.0 ]
let s = 5.

m * m
//val it : Matrix<float> =
//  DenseMatrix 3x3-Double
//30  66  102
//36  81  126
//42  96  150

v * v
//val it : float = 1400.0

重载

type Mult = Mult with
    static member inline ( $ ) (Mult, m1:Matrix<float>) = fun (m2:Matrix<float>) -> m1.Multiply(m2)
    static member inline ( $ ) (Mult, v1:Vector<float>) = fun (v2:Vector<float>) -> v1.DotProduct(v2)

let inline ( .*. ) v1 v2 = (Mult $ v1) v2

你可以这样使用它:

m .*. m
v .*. v

您将获得与上述相同的结果。您可以使用.*,我只是避免使用它,以免与已经定义的.* 混淆。现在这实际上在Global Operator OverloadingOveload operator in F# 中进行了讨论,但是 F# 的行为在这里有点模糊,所以我用 Matrix 和 Vector 类型重新做了示例。您可能可以使其通用。也许更熟悉 mathdotnet 的人可以提供更惯用的解决方案。您还应该检查 *.* 等。已经超载并按预期运行,因为对于常见操作,大多数这些东西是already implemented

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-06
    • 1970-01-01
    • 2015-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多