Seth Lastname | 1 Apr 02:21 2013
Picon

Layout section of Haskell 2010 Language Report -- Notes 1&2


I'm sure I'm missing something, but I'm having difficulty parsing or reconciling Note 1 and Note 2 of Section 10.3 ("Layout") of the Haskell 2010 Language Report.


Can somebody point me in the right direction?

To be clear, I'm not concerned with GHC behavior or best programming practices here, only with the specification of the language given in the Report.

Note 1 says, "A nested context must be further indented than the enclosing context ('n' > 'm'). If not, 'L' fails, and the compiler should indicate a layout error."

Note 2 says, "If the first token after a 'where' (say) is not indented more than the enclosing layout context, then the block must be empty, so empty braces are inserted."

It seems that, in Note 2, the "first token" necessarily refers to a lexeme other than '{' (else it would not make sense), in which case a '{n}' token will have been inserted after 'where' (in the example given in the note), yielding a nested context which is "not indented more than the enclosing layout context", and thus failing the test in the first sentence of Note 1.
So, in the places where Note 2 would apply, it seems Note 1 would yield a "layout error".

For example, in the following code (replace '.' with space),

f x = let
......g y = 2 * y
..........where
..g x

it seems that Note 1 would "layout error", yet this seems precisely the case addressed by Note 2 wherein "{}" would be inserted after the 'where' yielding syntactically correct (albeit strange) code.

Any insight would be appreciated.

Thanks,
Seth
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Malcolm Wallace | 2 Apr 11:43 2013

Re: Layout section of Haskell 2010 Language Report -- Notes 1&2


On 1 Apr 2013, at 01:21, Seth Lastname wrote:

> Note 2 says, "If the first token after a 'where' (say) is not indented more than the enclosing layout
context, then the block must be empty, so empty braces are inserted."
> 
> It seems that, in Note 2, the "first token" necessarily refers to a lexeme other than '{' (else it would not
make sense),

Correct.

> in which case a '{n}' token will have been inserted after 'where' (in the example given in the note),
yielding a nested context which is "not indented more than the enclosing layout context",

Yes, a "{n}" token has been inserted after the "where".
No, it does not yield an incorrectly nested context, because L is the function that decides whether to add to
the context.

Looking only at the three equations for L that deal with the pseudo-token "{n}", including their side
conditions, we see:

L ({n} : ts) (m : ms) = {  :  (L ts (n : m : ms)) if n > m (Note 1)
L ({n} : ts) []       = {  :  (L ts [n])          if n > 0 (Note 1)
L ({n} : ts) ms       = {  :  }  :  (L (< n >: ts) ms) (Note 2)

So, the third clause is triggered either when the nested-context stack (ms) is empty and n is zero or
negative; or when the context stack is non-empty and n<m.  That is, we avoid creating a context stack that
would be incorrect (according to Note 1).

Regards,
    Malcolm
Seth Lastname | 3 Apr 16:56 2013
Picon

Re: Layout section of Haskell 2010 Language Report -- Notes 1&2


Hi Malcolm,

Thank you for the thoughtful reply.

I understand you to make the [reasonable] assertion that the presence of "{n}" does not constitute a "nested context" because the existence of a "nested context" is determined by the state of the "context stack", and thus by L (rather than the mere presence of "{n}" in the input to L).

However, if you accept this interpretation of "nested context", then the second sentence and example of Note 1 do not seem to make sense.  That is, there does not seem to be a case where the test for the "layout error" described in Note 1 would be met.  Indeed, that test does not seem to even apply to the example that is given in Note 1 (the example code would produce a syntax error, but not be an example of the "layout error" defined in Note 1).
(Justification: the rules for pushing to the context stack seem to preclude pushing a value that is less than or equal to the top of the stack, except in the case of explicit braces which are allowed and clearly not the subject of Note 1.)

So, put as a question, given your reasonable interpretation of nested context, what is the purpose of the second sentence of Note 1 ("If not, ... layout error.")?

I.e., can we conclude that the second sentence of Note 1 is a NOOP and the example misleading or incorrect?

(To be clear, I very much appreciate the inclusion of notes and examples in the spec, especially where they might reveal a misunderstanding -- this one is just a minor sticking point for someone trying to write a correct parser.)

Thanks,
Seth

From: Malcolm Wallace <malcolm.wallace <at> me.com>
To: Seth Lastname <i_don.t_check_this <at> yahoo.com>
Cc: "haskell-cafe <at> haskell.org" <haskell-cafe <at> haskell.org>
Sent: Tuesday, April 2, 2013 5:43 AM
Subject: Re: [Haskell-cafe] Layout section of Haskell 2010 Language Report -- Notes 1&2


On 1 Apr 2013, at 01:21, Seth Lastname wrote:

> Note 2 says, "If the first token after a 'where' (say) is not indented more than the enclosing layout context, then the block must be empty, so empty braces are inserted."
>
> It seems that, in Note 2, the "first token" necessarily refers to a lexeme other than '{' (else it would not make sense),

Correct.

> in which case a '{n}' token will have been inserted after 'where' (in the example given in the note), yielding a nested context which is "not indented more than the enclosing layout context",

Yes, a "{n}" token has been inserted after the "where".
No, it does not yield an incorrectly nested context, because L is the function that decides whether to add to the context.

Looking only at the three equations for L that deal with the pseudo-token "{n}", including their side conditions, we see:

L ({n} : ts) (m : ms) = {  :  (L ts (n : m : ms)) if n > m (Note 1)
L ({n} : ts) []      = {  :  (L ts [n])          if n > 0 (Note 1)
L ({n} : ts) ms      = {  :  }  :  (L (< n >: ts) ms) (Note 2)

So, the third clause is triggered either when the nested-context stack (ms) is empty and n is zero or negative; or when the context stack is non-empty and n<m.  That is, we avoid creating a context stack that would be incorrect (according to Note 1).

Regards,
    Malcolm

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Gmane