SML Warning: Type Vars Not Generalized when using Empty Lists or NONE option

眉间皱痕 提交于 2019-12-30 08:07:18

问题


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 
  [] => raise MyException
  | head :: rest => case f head of 
                    SOME v => v
                    | NONE => my_func f rest

fun f a = 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 the warning:

Warning: type vars not generalized because of value restriction are instantiated to dummy types (X1,X2,...)

Whenever I pass in an options list containing at least one SOME value, this Warning is not thrown. I know it must be something to do with the fact that I am using polymorphism in my function currying, but I've been completely stuck as to how to get rid of these warnings.

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


回答1:


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:

  • literals (constants)
  • variables
  • function expressions
  • constructors (except for ref) applied to non-expansive values
  • a non-expansive values with a type annotation
  • tuples where each field is a non-expansive value
  • records where each field is a non-expansive value
  • lists where each field is a non-expansive value

All 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



来源:https://stackoverflow.com/questions/14668433/sml-warning-type-vars-not-generalized-when-using-empty-lists-or-none-option

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!