4

I am stuck attempting to overload the (*) operator for a Measure type.

What I would like to see is :

> let x = 1.0<i> * 1.0<i>;;

val x : float = -1.0

The following definition appears to do the trick :

> let inline (*) (v1 : float<i>) (v2 : float<i>) = float(-1) * float(v1) * float(v2);;

val inline ( * ) : float<i> -> float<i> -> float

Note that the product measure in this example correctly resolves to <1> as which happens for example when multiplying the imaginary unit of a complex number. Without this overloading definition the default product resolves to < i^2>.

But the overloading definition above has the nasty side effect that :

> let y = 1.0 * 1.0;;

let y = 1.0 * 1.0;;
--------^^^

stdin(11,9): error FS0001: This expression was expected to have type
float<i>    
but here has type
float

Apparently my overloading definition hides the (*) operator for the float type.

What am I doing wrong?

ebaklund
  • 271
  • 1
  • 6
  • `i` is not a generic unit, but a specific unit called `i`. You want `float<'a>`. – Ramon Snir Jan 02 '13 at 12:28
  • You aren't trying to write your own `System.Numerics.Complex`, are you? – Be Brave Be Like Ukraine Jan 02 '13 at 12:58
  • 1
    bytebuster : Most standard libraries define a complex type in terms of operations on real values. That way of implementing a complex type is both practical and possibly the only way to define the complex type given the tools of the implementing language. However, this way of defining a complex number misses out on some some basic concepts in the mathematical definition. F# gives the opportunity to define the complex type as a linear combination of some base units for which inner products are either +1 or -1: type Complex = { Real : float<1>; Imaginary : float; } – ebaklund Jan 02 '13 at 15:25

1 Answers1

5

Note that you are redefining the (*) operator rather than overloading it.

The trick to get it working is to write something using an intermediate type, like this:

type Mult = Mult with
    static member        ($) (Mult, v1: float<i>) = fun (v2: float<i>) -> 
                                 float(-1) * float(v1) * float(v2)
    static member inline ($) (Mult, v1      ) = fun v2 -> v1 * v2
    static member        ($) (Mult, v1: Mult) = fun () -> Mult //Dummy overload

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

BTW funny way to use units of measure.

Gus
  • 25,839
  • 2
  • 51
  • 76
  • Hi @ebaklund if this or any answer has solved your question please consider [accepting](http://meta.stackexchange.com/q/5234/179419) it by clicking the check-mark. This indicates to the wider community that you've found a solution and gives some reputation to both the answerer and yourself. There is no obligation to do this. – Gus Sep 17 '17 at 08:39