F # explicit element restrictions: a variable of type ^ T cannot be generalized because it cannot go out of its scope

I am trying to use explicit element restrictions in F #. The documentation states that "F # supports the full set of restrictions supported by the common language environment," but if I really compile the class with such an explicit restriction, for example, as follows, I get a rather exotic error.

type MyType<'T when ^T: (static member ( + ) : ^T * ^T -> ^T)> = member this.F ab = a + b 

Reports

error FS0670: this code is not general enough. The type variable ^ T, when ^ T: (static term (+): ^ T * ^ T โ†’ ^ T), cannot be generalized because it does not hide.

And reports this on the site definition member this.F What does it mean? What is the corresponding scope?

There are a number of approaches supported by the language for performing this kind of work. A good study can be found at https://stackoverflow.com/a/3166/ ... but I have not seen a clear explanation of why this particular generic restriction is not allowed to run away.

+7
generics f #
May 05 '11 at 22:15
source share
3 answers

Specification F #:

The form type ^ ident is the statically permitted type of the variable. a type variable created and added to the type (see ยง14.6). This type variable is labeled with an attribute indicating that it cannot be generalized, with the exception of the built-in ones (see ยง 14.7), as well as a variable of any type with which it is equated by the type inference equation cannot be generalized in the same way.

http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec.html

+1
May 05 '11 at 22:33
source share

Member restrictions require statically permitted type parameters. But parameters of statically permitted types are not allowed to types (as in your example), only for built-in functions and built-in methods.

The main problem is probably that types in general cannot be inline.

See also: http://msdn.microsoft.com/en-us/library/dd548046.aspx

If you use the inline element as follows:

 type MyType() = member inline this.F ab = a + b 

types a and b will automatically be correctly limited.

+8
May 05 '11 at 22:47
source share

You need to mark the inline element (and add type annotations if you want the arguments to be of type ^T ):

 type MyType<'T when ^T: (static member ( + ) : ^T * ^T -> ^T)>() = member inline this.F (a:^T) (b:^T) = a + b 

I also added a constructor so you can actually call the method:

 MyType().F 1 2 

As others have noted, it is rarely necessary to write explicit restrictions for members manually, as they are usually inferred. In addition, in this case there is no reason to place a constraint on the type, not the method, and the type parameterized by the statically allowed type variable is not idiomatic.

+3
May 6 '11 at 1:00 a.m.
source share



All Articles