SML warning: the Vars type is not generic when using empty lists or the NONE option

I canโ€™t understand for life why the following SML function throws a warning into my home problem:

fun my_func f ls = case ls of [] => raise MyException | head :: rest => case f head of SOME v => v | NONE => my_func f rest fun fa = if isSome a then a else NONE; 

Whenever I call my_func with the following test functions:

 my_func f [NONE, NONE]; my_func f []; 

I always get a warning:

Attention: the vars type is not generalized due to the restriction of the value created for dummy types (X1, X2, ...)

Whenever I pass a list of options containing at least one SOME value, this warning is not thrown. I know that this should be due to the fact that I use polymorphism in my function, but I am completely fixated on how to get rid of these warnings.

Please help if you have any ideas - thanks in advance!

+8
sml smlnj
source share
1 answer

Limiting the value referenced by the warning is one of the most difficult things to understand in SML, however I will do my best to explain why this happens in this case and try to point you to a few resources to find out more.

As you know, SML will use type inference to output most types in your programs. In this program, the type my_func will be defined as ('a -> 'b option) -> 'a list -> 'b . As you noted, this is a polymorphic type. When you call my_func as follows

 myfunc f [NONE, SOME 1, NONE]; 

... variables of type 'a and 'b are created on int option and int .

However, when you call it without value, for example SOME 1 above

 myfunc f [NONE, NONE]; 

What type variables do you think should be created? Types should be polymorphic - something like the 't option and 't for all types of 't . However, there is a limitation that prevents values โ€‹โ€‹such as polymorphic types.

SML defines some expressions as non-expanding values, and only these values โ€‹โ€‹can take polymorphic types. It:

  • literals (constants)
  • Variables
  • function expressions
  • constructors (other than ref ) applied to non-expansion values
  • non-extensible values โ€‹โ€‹with type annotation
  • where each field is a non-expansion value
  • records where each field is a non-expansion value
  • lists where each field is a non-expansion value

All other expressions, in particular function calls (which is a call to my_func ) , cannot be polymorphic . There are also no links. You might be interested to know that the following warning does not raise:

  fn () => my_func f [NONE, NONE]; 

Instead, the type is deduced unit -> 'a . If you want to call this function, you will again receive a warning.

My understanding of the reason for this restriction is a little weak, but I believe that the main problem with the root is mutable links. Here is an example that I took from the MLton website linked below:

 val r: 'a option ref = ref NONE val r1: string option ref = r val r2: int option ref = r val () = r1 := SOME "foo" val v: int = valOf (!r2) 

This program does not validate type in SML due to value limitation. If not for the limitation of value, this program would have a type error at runtime.

As I said, my understanding is precarious. However, I hope that I have shed a little light on the problem that you are facing, although I believe that in your case you can safely ignore the warning. Here are some guidelines if you decide you want to dig deeper:

http://users.cis.fiu.edu/~smithg/cop4555/valrestr.html

http://mlton.org/ValueRestriction

(By the way, the MLton site is solid gold . There is so much hiding there, so if you are trying to understand something strange in SML, I highly recommend looking here because you are likely to turn a lot more than you originally wanted)

Since it seems that you are actually using SML / NJ, this is a pretty handy guide to the error messages and warnings it will give you during compilation:

http://flint.cs.yale.edu/cs421/smlnj/doc/errors.html

+17
source share

All Articles