First of all, I think I do not fully understand why you need to state that the type parameter of the interface supports addition - I suppose addition would be used in the implementation of MyFunction
, in which case the callers of the interface do not need to know about it. If you want to expose addition, you could simply add it as a separate method:
type IMyInterface<'T> =
abstract Add : 'T * 'T -> 'T
abstract MyFunction : 'T -> 'T
I think static member constraints do not work very well in other places than in inline
functions or inline
static members (but I may be wrong). If you need to use numeric operations inside a generic type, you can use a trick that captures the implementations (in an inline
method) and stores them in an interface. There is an example of this at the end of my blog about generic math in F#.
The trick is to define an interface with the numeric operations you need and pass it as an additional argument to the constructor:
type IAddition<'T> =
abstract Add : 'T * 'T -> 'T
type MyType<'T>(a:'T, b:'T, add:IAddition<'T>) =
member x.Sum = add.Add(a, b)
So far, this is using interfaces in a standard .NET way - the interface represents the numeric operations and we invoke them via the interface. Now, the trick is to add inline
method Create
that takes just the two arguments and requires +
as a static constraint. The method can then implement the interface and pass it to the MyType
as a last parameter:
static member inline Create(a:^N, b:^N) =
let ops =
{ new IAddition< ^N > with
member x.Add(a, b) = a + b }
MyType< ^N >(a, b, ops)
Now you can write MyType<_>.Create(1, 2)
and the +
operation for integers will be automatically captured and stored in an interface (which is easier to work with in the rest of your code).