Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add type constraint to derived type F# (This code is not sufficiently generic)

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?

like image 669
mateuszlewko Avatar asked Nov 27 '16 14:11

mateuszlewko


1 Answers

Tomas's answer is good. However, for completeness: it is possible to use statically resolved type parameters on types:

type MovingSum< ^T when ^T : (static member (+) : ^T * ^T -> ^T)>(initial : ^T) =
    let mutable sum = initial

    member inline this.Add(x:^T) = sum <- sum + x

let m = MovingSum(1) in m.Add(3) // works!

But note that:

  1. Member constraints need to be included where the parameter is declared.
  2. I get a few spurious warnings here, indicating that maybe this language feature is not fully-baked...
  3. This doesn't help you anyway, since interface members can't be inlined - given a value of an interface type, the compiler doesn't have any way to determine the runtime type that implements the interface, and so it's impossible to know what implementation to inline.
like image 84
kvb Avatar answered Sep 21 '22 02:09

kvb