Proposal: Non-recursive let

oleg at oleg at
Wed Jul 10 10:48:43 CEST 2013

[reposting to Haskell-prime]

Jon Fairbairn wrote:
> It just changes forgetting to use different variable names because of
> recursion (which is currently uniform throughout the language) to
> forgetting to use non recursive let instead of let.

Let me bring to the record the message I just wrote on Haskell-cafe

and repeat the example:

In OCaml, I can (and often do) write

        let (x,s) = foo 1 [] in
        let (y,s) = bar x s in
        let (z,s) = baz x y s in ...

In Haskell I'll have to uniquely number the s's:

        let (x,s1)  = foo 1 [] in
        let (y,s2)  = bar x s1 in
        let (z,s3)  = baz x y s2 in ...

and re-number them if I insert a new statement. 

I once wrote about 50-100 lines of code with the fragment like the
above and the only problem was my messing up the numbering (at one
place I used s2 where I should've used s3). In the chain of lets, it
becomes quite a chore to use different variable names -- especially as
one edits the code and adds new let statements.

I have also had problems with non-termination, unintended recursion. 
The problem is not caught statically and leads to looping, which may
be quite difficult to debug. Andreas should tell his story.

In my OCaml experience, I don't ever remember writing let rec by
mistake. Occasionally I write let where let rec is meant, and the type
checker very quickly points out a problem (an unbound identifier).
No need to debug anything.

Incidentally, time and again people ask on the Caml list why 'let' in
OCaml is by default non-recursive. The common answer is that the
practitioners find in their experience the non-recursive let to be a
better default. Recursion should be intended and explicit -- more
errors are caught that way.

Let me finally disagree with the uniformity principle. It may be
uniform to have equi-recursive types. OCaml has equi-recursive types;
internally the type checker treats _all_ types as (potentially)
equi-recursive. At one point OCaml allowed equi-recursive types in
user programs as well. They were introduced for the sake of objects;
so the designers felt uniformly warrants to offer them in all
circumstances. The users vocally disagreed. Equi-recursive types mask
many common type errors, making them much more difficult to find. As
the result, OCaml developers broke the uniformity. Now, equi-recursive
types may only appear in surface programs in very specific
circumstances (where objects or their duals are involved). Basically,
the programmer must really intend to use them.

Here is an example from the natural language, English. Some verbs go from
regular (uniform conjugation) to irregular:

More information about the Haskell-prime mailing list