Robur_131
Robur_131

Reputation: 694

F# value restriction problem in reversing list

The following F# code doesn't compile due to value restriction problem:

let x = List.rev []

But this compiles:

let x = List.rev [] in 3::x

As I understand it, the compiler infers that x must be of type int list so it doesn't compile.

The following doesn't compile:

let x = List.rev [] in (3::x, true::x)

But this does:

let x = ([]) in (3::x, true::x)

Why?

Upvotes: 1

Views: 74

Answers (1)

Brian Berns
Brian Berns

Reputation: 17038

As I understand it*, there are two ways to declare a value in F#:

  • Value has a concrete type (e.g. List<int>). You must either explicitly specify this concrete type, or the compiler must be able to infer it.
  • Value has a generic type (e.g. List<'t>). You must either explicitly specify this generic type, or the compiler must be able to infer it and the value must be a simple immutable value.

With that in mind, here are the explanations for what you're seeing:

// not allowed because x is generic, but not simple
let x = List.rev []

// allowed because the compiler can infer x's concrete type (List<int>)
let x = List.rev [] in 3::x

// not allowed because x is generic, but not simple
let x = List.rev [] in (3::x, true::x)

// allowed because x is both generic and simple (compiler can tell it's the empty list)
let x = ([]) in (3::x, true::x)

* The value restriction can be tricky, so there may be nuances I've overlooked in my explanation.

Upvotes: 5

Related Questions