1

The following gives a duplicate definition error:

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

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

Is there a way to define an operator overload such that F# recognizes the function I'm trying to call based on the function signature?

For example Julia has this very useful feature:

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
...

It would be great if there were a way to replicate something similar in F#.

TylerH
  • 20,799
  • 66
  • 75
  • 101
  • F# does extensive type inference, and doesn't play nice with function/operator overloading. You will need to inline or put it in a class. – s952163 Jul 25 '16 at 03:57
  • In fact it seems that you cannot overload operators in extension members... – s952163 Jul 25 '16 at 05:25
  • 1
    Possible duplicate of [Functions with generic parameter types](http://stackoverflow.com/questions/501069/functions-with-generic-parameter-types) – Jwosty Jul 25 '16 at 18:25
  • Btw, I took a look at Julia, it's nice but obviously this is one its strengths: 'Julia programs are organized around multiple dispatch; by defining functions and overloading them for different combinations of argument types, which can also be user-defined. ' – s952163 Jul 25 '16 at 22:39

1 Answers1

2

In this specific case * is already overloaded. For example:

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

With overloading:

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

And you can use it like this:

m .*. m
v .*. v

You'll get the same results as above. You can use .*, I just avoided it as not to get confused with the already defined .*. Now this is actually discussed in Global Operator Overloading and Oveload operator in F# but F#'s behavior here is a bit obscure so I re-did the example with the Matrix and Vector types. You can probably make it generic. Maybe someone more familiar with mathdotnet can provide a more idiomatic solution. You should also check if * , .* et al. are already overloaded and function as expected for you since for common operations most of this stuff is already implemented.

Community
  • 1
  • 1
s952163
  • 6,276
  • 4
  • 23
  • 47