Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Indentation within a do block with infix operator

Tags:

haskell

I was reading on indentation rules when I stumbled across:

y :: [Int]
y = do
  c <- [4, 4, 4]
  return c
  ++ [1]           -- line 5

Because of

if it is indented the same amount, then a new item begins (a semicolon is inserted);

I expected a ; in front of ++ (on line 5) which should give a parse error but seems to be fine (example). This is confusing me.

y :: [Int]
y = do{
  ;c <- [4, 4, 4]
  ;return c
  ;++ [1]}         -- I expected a ';' here and thus a parse error

What am I missing?

like image 440
Micha Wiedenmann Avatar asked Apr 08 '20 07:04

Micha Wiedenmann


1 Answers

The paragraph you are quoting starts with:

Informally stated,

and it is indeed just a quick overview of what is happening, meant to give you some intuition. The formal rules are in section 10.3 Layout.

What happens in your case is that your code gets changed into:

y :: [Int]
y = do 
  { c <- [4, 4, 4]
  ; return c
  ; ... {- we are here -}

the last rule applied being, indeed:

L (<n> : ts) (m : ms) = ; : (L ts (m : ms)) if m = n 

However note that emitting ++ now would cause a parse error, and thus this rule kicks in:

L (t : ts) (m : ms) = } : (L (t : ts) ms) if m∕ = 0 and parse-error(t)
                                                        (Note 5) 

So a closing brace is emitted instead and after that the lexer proceeds normally.

In the end, your code is parsed as:

```haskell
y :: [Int]
y = do 
  { c <- [4, 4, 4]
  ; return c
  ; } ++ [1]

Actually, the overview section mentions this behaviour too (although, admittedly, it is not particularly easy to understand what it says):

A close brace is also inserted whenever the syntactic category containing the layout list ends; that is, if an illegal lexeme is encountered at a point where a close brace would be legal, a close brace is inserted.

like image 102
kirelagin Avatar answered Nov 06 '22 15:11

kirelagin