[Haskell-cafe] Indentation woes

Tillmann Rendel rendel at rbg.informatik.tu-darmstadt.de
Thu Jul 26 22:02:20 EDT 2007


Stefan O'Rear wrote:
> Out of curiousity, what do you find objectionable about (legal):
> 
> function argument argument2
>  | guard = body
>  | guard = body
> 
> as compared to (currently illegal):
> 
> function argument argument2
> | guard = body
> | guard = body

I see the vertical strokes as visually lining up, pointing at something. 
In the legal example, they are pointing to the second character of the 
function name, wich has no meaning, but in the currently illegal 
example, they are pointing to the function name as a whole, wich has a 
meaning: To see wich function we are defining here, follow the vertical 
strokes upwards. (I don't need the strokes to show me that, of course, I 
just don't want them to distract me by pointing at a random position).

As I understand it, the idea behind layout is to use indention to 
express tree-like structures in plain text:

   root
     first level node
       second level node
       another second level node
     another first level node
       second level node in a different subtree

This is fine as long as no vertical strokes show up at the beginning of 
lines, since vertical strokes are sometimes used to express
tree-like structures in plain text, too:

   root
   | first level
   | | second level
   | | another second level node
   | another first level node
   | | second level node in a different subtree

The plain text parser embedded into my eyes seems to expect something 
like the latter tree encoding when it sees vertical strokes at the 
beginning of lines, but Haskell layout works more like the former.

To help my eyes, I try to write the whole pattern in a single line.

   function argument argument2 | guard1 = body1
                               | guard2 = body2

If lines get too long this way, I wrap the body, not the pattern:

   function argument argument2 | guard1 =
       body1

   function argument argument2 | guard2 =
       body2

Of course, if I want to have local definitions visible to both bodies, I 
have to write something like this:

   function argument argument2 = result where
       result | guard1 = body1
       result | guard2 = body2
       helper = ...
       other_stuff = ...


I don't think this is a layout problem, I think this is a pattern syntax 
problem. (Or it may be a problem of my eyes). As I understand it, the 
layout rule is not made for stuff starting with keywords, but for stuff 
starting with identifiers, to avoid having to use keywords. But "|" is 
clearly a keyword here. So if I were to design it, I would try to get 
rid of the repeated "|" keyword, maybe allowing the running example to 
be written as

   function argument argument2 |
       guard1 = body1
       guard2 = body2

wich seems to be much clearer for my eyes. Another option would be

   function argument argument2 = guard1 -> body1
                               | guard2 -> body2

wich is good because "|" now works like in data defintions, meaning 
"alternatively", but bad because the "pattern matching stops when 
crossing the equals sign"-rule no longer holds.

   Tillmann


More information about the Haskell-Cafe mailing list