7
votes

In Haskell, declaration order in let/where constructs does not matter, for example:

f x = let g1 x y = if x>y then show x else g2 y x
          g2 p q = g1 q p
      in ...

where g2 used in g1 before its declaration. But this is not a case in Ocaml:

# let a = b in
  let b = 5 in
  a;;
Warning 26: unused variable b.
Error: Unbound value b

Is there a reason why OCaml doesn't behave like Haskell? In the absence of forward declaration, this feature seems useful to me.

Is it because of strict evaluation in OCaml but lazy in Haskell?

4
Note that in Haskell, the direct translation let a = b in let b = 5 in a is still illegal.Fred Foo

4 Answers

20
votes

OCaml uses "let rec" to indicate when the binding in a group can refer to each other. Without the extra "rec" the binding must be in top-down order. See "local definitions" at http://caml.inria.fr/pub/docs/manual-ocaml/expr.html for details.

7
votes

Not the strictness as such, but that's a symptom of the same problem.

Ocaml is not purely functional, which is to say that arbitrary function calls can do arbitrary I/O. This requires them to run in a predictable order, which requires both strictness and the let-ordering you've noticed.

5
votes

In Haskell it's not because of lazy evaluation. Figuring out which name refers to what happens at compile time, when anyway nothing is being executed (strictly or lazily). Remember in Haskell you're only writing mathematical definitions, not commands to be executed in order. In what order you write these definitions does not matter. Whether you say

a = expr1
b = expr2

or

b = expr2
a = expr1

it means that a is defined to be expr1 and b is defined to be expr2.

I don't know any OCaml, so can't say anything about that.

-1
votes

Haskell did away with the archaic let vs. let rec distinction. A decent compiler can see very well if it's a simple let or one that contains mutually recursive definitions and can act accordingly.

(I wonder what a ML compiler does if one starts with let rec and then only has non recursive definitions. Surely, this let/let rec thing is a nasty obstacle when one does some refactoring.)