2

In F#, I have defined an interface with a generic member:

type MyType =
    abstract MyMember<'a> : 'a -> int

I would like to write a function that can create an object that implements this interface:

module MyType =

    let create f =
        {
            new MyType with
                member __.MyMember(x) = f x
        }

This currently fails to compile with the following error message:

This code is not sufficiently generic. The type variable 'a could not be generalized because it would escape its scope.

Is it possible to make this work via inlining and static resolved type parameters (or something similar)? Thanks.

Brian Berns
  • 15,499
  • 2
  • 30
  • 40
  • 2
    Short answer - you can't do it. F# doesn't have higher-rank types, which in simpler terms means that functions lose their genericity when passed as values. This is somewhat related: https://stackoverflow.com/a/42599144/180286 – Fyodor Soikin May 06 '20 at 16:05

1 Answers1

1

An explanation for the compile error:

Object expressions construct anonymous classes - these are just regular classes, with a compiler generated name. You're essentially creating a closure which captures f.

This is how you'd normally implement it:

type MyType =
    abstract MyMember<'a> : 'a -> int

type MyNewType (f) =
    interface MyType with
        member _.MyMember x = f x

The type's constructor would have a parameter f of type 'a -> int, where 'a would normally be decided by the first usage of MyNewType.

But there's no way to generalize f such that it could be captured as a value that would satisfy the generic constraint of MyMember. Here sufficiently generic means a type of one order above the generic type.

Asti
  • 12,447
  • 29
  • 38