Value restriction explained

In programming languages with Hindley-Milner type inference and imperative features, in particular the ML programming language family, the value restriction means that declarations are only polymorphically generalized if they are syntactic values (also called non-expansive). The value restriction prevents reference cells from holding values of different types and preserves type safety.

A Counter Example to Type Safety

In the Hindley–Milner type system, expressions can be given multiple types through parametric polymorphism. But naively giving multiple types to references breaks type safety. The following are typing rules for references and related operators in ML-like languages.

\begin{align} ref&:\forall\alpha.\alpha\to(\alpharef)\\ !&:\forall\alpha.(\alpharef)\to\alpha\\ :=&:\forall\alpha.(\alpharef)\to\alpha\tounit \end{align}

The operators have the following semantics: \mathtt takes a value and creates a reference containing that value, \mathtt (dereference) takes a reference and reads the value in that reference, and \mathtt (assignment) updates a reference to contain a new value and returns a value of the unit type. Given these, the following program[1] unsoundly applies a function meant for integers to a Boolean value.let val c = ref (fn x => x)in c := (fn x => x + 1); !c trueendThe above program type checks using Hindley-Milner because c is given the type \forall \alpha . (\alpha \to \alpha)\ \mathtt, which is then instantiated to be of the type (\mathtt \to \mathtt)\ \mathtt when typing the assignment c := (fn x => x + 1), and (\mathtt \to \mathtt)\ \mathtt ref when typing the dereference !c true.

The Value Restriction

Under the value restriction, the types of let bound expressions are only generalized if the expressions are syntactic values. In his paper, Wright considers the following to be syntactic values: constants, variables, \lambda-expressions and constructors applied to values. The function and operator applications are not considered values. In particular, applications of the

ref

operator are not generalized. It is safe to generalize type variables of syntactic values because their evaluation cannot cause any side-effects such as writing to a reference.

The above example is rejected by the type checker under the value restriction as follows.

int\toint

, but is applied to a value of type \mathtt, and the type checker rejects the program.

See also

References

External links

Notes and References

  1. Wright. Andrew K.. 1995-12-01. Simple imperative polymorphism. LISP and Symbolic Computation. en. 8. 4. 343–355. 10.1007/BF01018828. 19286877 . 1573-0557.