Why do I get the following warning in SML:

- val id = map (fn n => n);
! Warning: Value polymorphism:
! Free type variable(s) at top level in value identifier id
> val id = fn : 'a list -> 'a list

I can see that id is polymorphic, but why should this be a problem? The anonymous function is completely polymorphic as well.

asked 27 Dec '11, 00:09

Sebastian%20Paaske%20T%C3%B8rholm's gravatar image

Sebastian Pa... ♦♦
86531133
accept rate: 41%

edited 10 Jan '12, 13:50

Nana%20Girotti's gravatar image

Nana Girotti ♦
1164


In reality Standard ML is not a functional language. Rather it is functional in ideology, but there is an imperative subset of the language that makes the whole language imperative in practice. For example,

 val r = ref 5;
 r := 7;
 (!r) + 37

Which creates a ref(-erence) cell containing the value 5, overwrites the contents of the cell with 7 and then asks for the contents while adding by 37. This yields the result 44. This is an example of an effect in the standard ML language. Here the side effect is that we update the cell.

It turns out that allowing these kinds of constructions in the SML language yields problems when you begin to mix it with polymorphism. As an example, I can define:

 val r = ref (fn x => x)

Which, if it were accepted looks innocent. It must have type ('a -> 'a) ref. But, notice that another section, another module of my program might overwrite the contents:

 r := (fn x => x + 1)

so the contents suddenly has type (int -> int) ref. Now this seems valid. If it had 'a -> 'a in the original variant, then surely I can specialize it locally to int -> int. But then the troube is there! In another part of my program, I have written:

 !r true

with a type of (bool -> bool) ref. But now the type system is in grave trouble. One place we restricted 'a to int whereas here the restriction is bool. The ref-cell acts like a "channel" through which we can circumvent the type system.

So, the solution in Standard ML is to limit polymorphic values in certain ways. This limitation has the codeword of the value restriction in the SML '97 standard and it is purely syntactical. It denies the above construction, so the trouble is not there. This ensures that the type system is still sound and works as expected.

Here is the original example:

 val id = map (fn n => n)

The rule in Standard ML is that when we have something of the form

 val x = e

then e will only be polymorphic if it is a so-called non-expansive expression, also called a syntactic value (at the top level, put it inside a let to make it monomorphic and it will work). There are rules for forming syntactic values. Literals, identifiers are syntactic values. So are function values like fn x => x. And also constructors with syntactic values in them. But function calls are not syntactic values.

This explains why

val foo = fn x => x

will work. It is a syntactic value, or a non-expansive expression. But since map is a function call, the original example,

val lid = map (fn x => x)

is not. And hence it is ruled out. The precise definition of what a syntactic value is, is to be found in the Definition of Standard ML :)

link

answered 06 Jan '12, 20:16

jlouis's gravatar image

jlouis
6163
accept rate: 50%

edited 23 Jan '12, 19:22

Idéen er at spørgsmål der stilles på engelsk også besvares på engelsk. Vi vil gerne have at det bliver et forum der også kan bruges af internationale studerende, men samtidig ikke begrænser sig fra ting der er svære at udtrykke på andet end dansk.

Men lækkert at du gider bruge tid på at uddanne DIKUfanterne jlouis! I dette tilfælde vil det nok være lettere hvis Sebastian retter spørgsmålet til at stå på dansk :-)

(06 Jan '12, 20:50) Martin Dybdal ♦♦ Martin%20Dybdal's gravatar image
1

Eller også omskriver jeg det lige til internationalt :P

(06 Jan '12, 22:54) jlouis jlouis's gravatar image

Then (1) why does it give warnings when there are no ref cells (like in Nana's example), and (2) why does it not give warnings with all polymorphism at the top level? (E.g. val id = fn x => x)

The explanation that was given to me is that the program analysis is shallow and assumes that a ref cell could be in use the moment a function application happens in which a polymorphic value is passed (e.g. map (fn x => x), in which (fn x => x) is polymorphic and is passed as value to map). A smarter compiler could label syntax trees as pure/impure and reduce warnings from code in which ref cells do not occur.

(23 Jan '12, 19:12) Simon Shine ♦ Simon%20Shine's gravatar image

Your prayers have been heard. I added a blurb as the answer, but you should probably have made it a comment :)

(23 Jan '12, 19:23) jlouis jlouis's gravatar image
Your answer
toggle preview

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "title")
  • image?![alt text](/path/img.jpg "title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Tags:

×122
×7

Asked: 27 Dec '11, 00:09

Seen: 1,513 times

Last updated: 23 Jan '12, 20:02

powered by OSQA