I can\'t for the life of me figure out why the following SML function is throwing a Warning in my homework problem:
fun my_func f ls =
case ls of
[]
The value restriction referenced in the warning is one of the trickier things to understand in SML, however I will do my best to explain why it comes up in this case and try to point you towards a few resources to learn more.
As you know, SML will use type inference to deduce most of the types in your programs. In this program, the type of my_func
will be inferred to be ('a -> 'b option) -> 'a list -> 'b
. As you noted, it's a polymorphic type. When you call my_func
like this
myfunc f [NONE, SOME 1, NONE];
... the type variables 'a
and 'b
are instantiated to int option
and int
.
However when you call it without a value such as SOME 1
above
myfunc f [NONE, NONE];
What do you think the type variables should be instantiated to? The types should be polymorphic -- something like 't option
and 't
for all types 't
. However, there is a limitation which prevents values like this to take on polymorphic types.
SML defines some expressions as non-expansive values and only these values may take on polymorphic types. They are:
ref
) applied to non-expansive valuesAll other expressions, notably function calls (which is what the call to my_func
is) cannot be polymorphic. Neither can references. You might be curious to see that the following does not raise a warning:
fn () => my_func f [NONE, NONE];
Instead, the type inferred is unit -> 'a
. If you were to call this function however, you would get the warning again.
My understanding of the reason for this restriction is a little weak, but I believe that the underlying root issue is mutable references. Here's an example I've taken from the MLton site 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 typecheck under SML, due to the value restriction. Were it not for the value restriction, this program would have a type error at runtime.
As I said, my understanding is shaky. However I hope I've shed a little light on the issue you've run into, although I believe that in your case you could safely ignore the warning. Here are some references should you decide you'd like to dig deeper:
http://users.cis.fiu.edu/~smithg/cop4555/valrestr.html
http://mlton.org/ValueRestriction
(BTW the MLton site is solid gold. There's so much hidden away here, so if you're trying to understand something weird about SML, I highly recommend searching here because you'll likely turn up a lot more than you initially wanted)
Since it seems like you're actually using SML/NJ, this is a pretty handy guide to the error messages and warnings that it will give you at compile time:
http://flint.cs.yale.edu/cs421/smlnj/doc/errors.html