The Do-Let-Braces problem

Mark Utting
Thu, 15 Feb 2001 15:20:19 +1300

Summary: Haskell layout has problems within 'do' (see below).  
         Can we change Haskell to improve it?

We teach Haskell to all our second-year students, and we 
like to teach the OPTION of using explicit braces and ;'s.
(If students write nested do constructs, even though we discourage this,
 they often have trouble with the layout rules.)

We would like to be able to teach this:
  "To use explicit structuring, instead of layout, you can just
   put braces around all the statements in a 'do' block,
   plus semicolons at the end of each statement. (like in C++/Java!)."

But this does not work.  For example, the first definition below
parses, but the second does not.

fa::IO ()
fa = 
        putStr "Enter Data: "
        line <- getLine
        let line2 = line
        putStr line2
fb::IO ()
fb = 
    do {
        putStr "Enter Data: ";
        line <- getLine;
        let line2 = line;
        putStr line2;

ERROR "f.hs" (line 13): Syntax error in definition 
            (unexpected symbol "putStr")  

Fix 1: Put explicit braces around the body of the 'let':

        let {line2 = line};

       This is ugly and a nuisance to teach.  It would be much nicer to be
       able to teach 'let pattern = expr' as a simple statement, and avoid 
       mentioning the possibility of multiple definitions within
       a single 'let'.  (Which is rarely needed within 'do' syntax
       anyway, because you can usually use several separate let statements
       instead.  Mutually recursive definitions is probably the only reason.)

Fix 2: an alternative fix is to move the semicolon at the end of the let
       to the beginning of the next line, but this is ugly!

f2 = 
    do {
        putStr "Enter Data: ";
        line <- getLine;
        let line2 = line
        ;putStr line2

Fix 3: I might be happy to put ALL the semicolons at the beginning
       of lines, which also works, but you are not allowed a semicolon
       at the beginning of the first brace, so this looks asymmetric.
f3 = 
    do {
        putStr "Enter Data: "
        ;line <- getLine
        ;let line2 = line
        ;putStr line2

     Is it possible to change the layout handling of Haskell slightly 
     so that f1 is legal?  

     Perhaps the explicit semicolon at the end of the let line
     could terminate the (implicit) layout of the let statement?


Dr Mark Utting, Senior Lecturer
Department of Computer Science
School of Computing and Mathematical Sciences
The University of Waikato	Tel:   +64 7 838 4791
Private Bag 3105		Fax:   +64 7 858 5095
Hamilton			Email:
New Zealand			Web:

It is a time-proven principle of software engineering to try and 
strengthen the static description of systems as much as possible.
[Clemens Szyperski]