Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# overloading operators for generic types

I'm trying to define a module containing a generic type with operator overloading, but the mono compiler seems to ignore my types in the implementation file. My interface file looks like:

module Vector
[<Sealed>]
type Vector<'a> =
  static member ( +. ) : Vector<'a> * Vector<'a> -> Vector<'a>
val make : 'a * 'a -> Vector<'a>
val coord : Vector<'a> -> 'a * 'a

And my implementation is

module Vector
type Vector<'a> =
  | V of 'a * 'a
  static member ( +. ) (V(x1,y1), V(x2,y2)) = V(x1+x2, y1+y2)
let make (x, y) = V(x, y)
let coord (V(x, y)) = (x, y)

When I compile I get:

fsharpc -a VectorParam.fsi VectorParam.fs
F# Compiler for F# 3.1 (Open Source Edition)
Freely distributed under the Apache 2.0 Open Source License

/.../VectorParam.fs(4,19): error FS0034: Module 'Vector' contains
    static member Vector.( +. ) : Vector<int> * Vector<int> -> Vector<int>    
but its signature specifies
    static member Vector.( +. ) : Vector<'a> * Vector<'a> -> Vector<'a>    
The types differ

which I don't understand, since I'm using a tagged type. And, if I remove all "<'a>" and replace remaining type aliases with float, then everything works fine. Can anyone help me understand the right syntax?

Thanks, Jon

like image 892
Jon Sporring Avatar asked Feb 08 '23 17:02

Jon Sporring


1 Answers

I would start by ditching the fsi file - it is not really required. If you really need it, the easiest way to create it is by pasting your file into fsi and copying the output, or you can get the compiler to generate one for you.

When doing type inference over numeric types it is best to use inline members. The reason is that F# really likes to use int - and as soon as it sees a + with no further constraints the compiler will infer int. This is because in the .NET type system, not all of the constraints used by F# can be expressed. Using inline bypasses this.

Here is a simple example that can be pasted straight into fsi:

type Vector<'a> =
  | V of 'a * 'a
  static member inline ( +. ) (V(x1,y1), V(x2,y2)) = V(x1+x2, y1+y2);;

V(1,1) +. V(1,1);;
V(1.,1.) +. V(1.,1.);;
like image 176
John Palmer Avatar answered Feb 15 '23 08:02

John Palmer