Different inferred type with or without rec keyword

file test.ml

let rec foo payload =
  if payload then bar (object (this) method foo = 1 end) else 1
and bar payload = if payload#foo > 1 then payload#foo else foo true
let baz payload = if payload#foo > 1 then payload#foo else foo true

running ocamlc -i test.ml

val foo : bool -> int
val bar : < foo : int > -> int
val baz : < foo : int; .. > -> int

The bar and baz has different types, what do you think? thanks!

This is a polymorphic recursion issue, rewriting the mutually recursive definition as

let rec foo payload =
  if payload then bar (object (this) method foo = 1 end)
  else 1
and bar: 'a. (<foo:int; ..> as 'a) -> _ = fun payload ->
  if payload#foo > 1 then payload#foo else foo true

yields the expected type for bar

val bar : < foo : int; .. > -> int

In a recursive definition such as let rec x = eā‚ in eā‚‚, the variable x can be used polymorphically in eā‚‚, but not in eā‚.

One way to understand that behaviour is to think of the definition as let x = fix (fun x -> eā‚) in eā‚‚. Within eā‚ the variable x is a function argument, while within eā‚‚ the variable x is a let-bound variable. Only let-bound variables can be used polymorphically in ML.

2 Likes

Indeed, my memory is a bit rusty, thanks!