I have this interface:
type IMovingFunc< 'T > =
abstract member Add : 'T -> unit
Now I want to create a generic type that implements Add function and uses (+) operator:
type MovingSum< ^T >(initial : ^T) =
let mutable sum = initial
interface IMovingFunc< ^T> with
member inline this.Add x = sum <- sum + x
Unfortunately, I'm getting this error:
This code is not sufficiently generic. The type variable ^T when ^T : (static member ( + ) : ^T * ^T -> ^T) could not be generalized because it would escape its scope.
I've tried adding type constraint to MovingSum but it didn't help:
type MovingSum< ^T when ^T : (static member ( + ) : ^T * ^T -> ^T)>(initial : ^T)
Could you please tell me how to fix this or is there other way to achieve this?
As mentioned by Fyodor in the comments, types cannot have statically resolved constraints in the same way as functions (mainly because static constraints are handled using inlining - and you cannot really inline a whole type).
One way to address this is to make the constraint explicit in the type and then create a function with static member constraint that captures the functionality and passes it to the type.
In your example, you need the +
operator, so we can add adder
as a parameter of the type:
type MovingSum<'T>(initial:'T, adder:'T -> 'T -> 'T) =
let mutable sum = initial
interface IMovingFunc<'T> with
member this.Add x = sum <- adder sum x
This does not require static member constraints, but you need to provide the extra parameter when creating MovingSum
. This is not too bad, but you can avoid that by defining an inline function that creates MovingSum
and captures the +
operator:
let inline movingSum initial =
MovingSum(initial, fun a b -> a + b) :> IMovingFunc<_>