2

I try to write a reverse function for a polymorphic list as shown.

let rev  =
  let rec impl_rec acc = function
    | []    -> acc
    | x::xs -> impl_rec (x::acc) xs 
  in impl_rec []

The compiler infers a type of

'_weak list -> '_weak list

However, If I provide the parameter explicitly.

let rev xs  =
  let rec impl_rec acc = function
    | []    -> acc
    | x::xs -> impl_rec (x::acc) xs 
  in impl_rec [] xs

The following code is able to infer the polymorphic type

'a list -> 'a list

There is no ref type. How does the OCaml Compiler infer the first version to a weak type?

Chris
  • 26,361
  • 5
  • 21
  • 42
Willi
  • 317
  • 1
  • 8

1 Answers1

4

This is the value restriction at work: https://ocaml.org/manual/polymorphism.html#s:weak-polymorphism . The value restriction makes a difference between values, for instance

fun x -> x,
Constructor value,
(value, value')

and computation

f x
{ contents = [] } (* contents is a mutable field *)

Outside of the relaxed value restriction (which applies mostly to empty containers), only syntactic values may be polymorphic and any computation is given a weakly polymorphic type. Typically, in your first implementation:

let rev =
   ...
   impl_rec []

the function rev is the result of a computation and thus cannot be made polymorphic. Contrarily, in

let rev = fun l -> ... impl_rec [] l

the function rev is syntactically a function and thus a syntactic value. Its type can therefore be generalized.

The pragmatic summary is that if you are building a function for later uses in OCaml, it is better to ensure that it is also a syntactic function to avoid the value restriction.

On a higher-level, this illustrates the fact that the value restriction is an approximation. It allows mutable values and polymorphism to coexist without unsoundness and without having to refine the type of functions into several different arrow types. But this come at the cost of some overly cautious introduction of weakly polymorphic type.

octachron
  • 17,178
  • 2
  • 16
  • 23
  • 1
    When you said "... and thus cannot be weakly polymorphic" what you meant was "... and thus can only be weakly polymorphic" – Chris Vine Jun 25 '22 at 10:53
  • 1
    You are right even if I prefer the formulation "cannot be made polymorphic" which better reflect let-polymorphism à la ML. – octachron Jun 25 '22 at 11:06