John Meacham john at
Wed May 14 06:20:25 UTC 2014

Okay, I believe I have come up with a modified version that accepts many more
programs and doesn't require complicated comma handling, you can make all
decisions based on the top of the context stack. It also allows many useful
layouts that were illegal under the old system.

The main change was to store the expected closing token in addition to the
opening one on the context stack, then look up the appropriate token in a
table based on the immediately enclosing context. Unlike the old version
that recursed up the stack, this only needs to look at the top.

The rules are (where _ means true everywhere)

always enabled:
        of => ('|','->')
        let => ('|','=')
        '[' => ('|',']')

then we follow the same rules as before, except we check the token against
the stored ending token at the top of the stack and 'let' is only terminated
by ',' if '|' is at the top of the context stack.

In addition I added a list of 'layout insensitive' symbols, that will never
poke the layout rule, they are ["|","->","=",";",","]. lines starting with
these will not continue or close layout contexts.

So, there are still a couple obscure cases this won't lay out properly, but
it does allow some handy things that were not allowed before.

it boils down to the fact that layout is turned off inside any enclosing
brackets and effects do not propagate outside of them. So nothing done
between [ .. ] can affect anything outside of them.

some handy things this allows

-- a 'cond' construct that lines up nicely.
foo = case () of ()
      | cond1 -> exp1
      | cond2 -> exp2
      | cond3 -> exp3

line up your tuple defs

,gamma) = foo

no need to double indent conditionals in do let

let f x y z
    | x == z = y
    | x == y = z
    | y == z = x

The simple rule is, inside enclosing brackets, layout is turned off and
doesn't propagate. I am testing the rules with ghc and they are promising so
far. pattern bindings


More information about the Glasgow-haskell-users mailing list