Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type variable escapes scope when combining generic and non-generic class

I have a generic class in F# with a single type parameter, and would like to create a static class containing factory methods. When I write my classes, the F# compiler generates an error related to a "type variable escaping its scope". My question is why the error is there and how to fix it.

I've created a minimum-size snippet demonstrating the issue:

type Foo<'a>(element : 'a) =

    member this.Copy () = Bar.Create(element)

and Bar =

    static member Create(element : 'a) = new Foo<'a>(element)

The mutual recursion in the types is there because I'd like the type Foo<'a> to be able to call the factory methods in the static class. The above snippet does not compile, and the error is: "Type inference caused the type variable a to escape its scope. Consider adding an explicit type parameter declaration or adjusting your code to be less generic." The error is registered as being located in the Create method of the Bar class. Unfortunately, I don't really understand the problem nor how to fix it. Any ideas?

Here's an additional observation. The snippet

type Foo<'a>(element : 'a) =

    member this.Element = element

and Bar =

    static member Create(element : 'a) = new Foo<'a>(element)

does compile. So the issue appears to be related to type inference made on the basis of the Copy() method of the Foo<'a> class. Furthermore, the snippet

type Foo<'a>(element : 'a) =

    member this.Copy () = Bar.Create(element)

and Bar =

    static member Create<'a>(element) = new Foo<'a>(element)

is a more C#-like version of the code (where the static method explicitly is made generic), which also does not compile, with the error "This code is not sufficiently generic. The type variable 'a could not be generalized because it would escape its scope."

like image 594
Alexander Sokol Avatar asked Jan 19 '17 16:01

Alexander Sokol


People also ask

Can a non-generic class have a generic method?

Yes, you can define a generic method in a non-generic class in Java.

What is generic type arguments?

The generic argument list is a comma-separated list of type arguments. A type argument is the name of an actual concrete type that replaces a corresponding type parameter in the generic parameter clause of a generic type. The result is a specialized version of that generic type.

Can we have non-generic method in generic class C#?

There he mentioned that it is possible to create generic method inside non-generic class.

Can generic class handle any type of data?

A generic class and a generic method can handle any type of data.


1 Answers

Type inference for recursive members often requires type annotations on at least some of the definitions. However, sometimes you can avoid this by re-ordering definitions, as you can in at least your simplified repro:

type Bar = 
    static member Create(element) = Foo(element)
and Foo<'a>(element:'a) =
    member this.Copy() = Bar.Create(element)

(note that I've even removed the annotation on element in Bar.Create).

I don't know that there's an easy-to-understand explanation of exactly what annotations will be needed in any particular situation, unfortunately.

like image 182
kvb Avatar answered Sep 23 '22 22:09

kvb