I like layout but I think the existing rules are too complicated. Unfortunately it's difficult to do anything with them without breaking vast swathes of existing code, so we'll just have to put up with them. The reason I think layout is better than using {'s and ,'s is that humans use the layout to group the structure anyway, which means you can have confusing situations where a structure looks alright to a human but not to a computer.
I like layout but I think the existing rules are too complicated. Unfortunat ely it's difficult to do anything with them without breaking vast swathes of existing code, so we'll just have to put up with them.
Well, there's two things to consider: Haskell 98, which probably shouldn't change, and extended Haskell, which probably should. Especially if we can make the rules both simpler and better.
The reason I think layout is better than using {'s and ,'s is that humans use the layout to group the structure anyway, which means you can have confusing situations where a structure looks alright to a human but not to a computer.
Which is exactly the problem with the programme I posted. Having thought about it a bit, it strikes me that the particular problem is the insertion of a closing brace. From the human reader's point of view, there's no visual equivalent of the closing brace in the example:
possible_int = do skip_blanks fmap Just int +++ (literal "-" `as` Nothing)
What happens is that a semicolon is inserted because the indentation is the same as the previous line -- that's fair enough, subject to some quibbles about treating all expressions the same -- but then the +++ is a syntax error unless a closing brace is inserted. Visually, the equivalent of a closing brace is when indentation is less (to my eye it ought to be right down to where the 'do' is and inbetween be an error). What's wrong with the notion that closing braces should only be inserted when the indentation is less (or the file ends)? This would reject some programmes, but only ones where the appearance is misleading. So
possible_int = do skip_blanks fmap Just int +++ (literal "-" `as` Nothing)
whatever ...
parses as
possible_int = do {skip_blanks ;fmap Just int +++ (literal "-" `as` Nothing)
} whatever ...
and
possible_int = do skip_blanks fmap Just int +++ (literal "-" `as` Nothing)
whatever ...
parses as
possible_int = do {skip_blanks ;fmap Just int ;+++ (literal "-" `as` Nothing)
} whatever ...
and then gives a syntax error but
possible_int = do skip_blanks fmap Just int +++ (literal "-" `as` Nothing)
whatever ...
parses as
possible_int = do {skip_blanks ;fmap Just int } +++ (literal "-" `as` Nothing)
whatever ...
Which is just about acceptable to me, because the +++ does stick out, though I'd prefer that one to be rejected too. I wasn't fit enough to follow the earlier discussions of the layout rule, so I'm not sure how this interacts with previous awkward cases. I'd be happiest if we could come up with a rule that didn't involve sticking in braces and semicolons because it won't parse otherwise. Can someone remind me why the "A close brace is also inserted whenever the syntactic category containing the layout list ends" part of the rule is there? Jón -- Jón Fairbairn Jon.Fairbairn@cl.cam.ac.uk 31 Chalmers Road jf@cl.cam.ac.uk Cambridge CB1 3SZ +44 1223 570179 (after 14:00 only, please!)
Jon Fairbairn wrote:
I wasn't fit enough to follow the earlier discussions of the layout rule, so I'm not sure how this interacts with previous awkward cases. I'd be happiest if we could come up with a rule that didn't involve sticking in braces and semicolons because it won't parse otherwise. Can someone remind me why the "A close brace is also inserted whenever the syntactic category containing the layout list ends" part of the rule is there?
It's so you can write let x = 2+2 in x*x (and similar things) I think this inserting a '}' when there would otherwise have been a syntax error is a terrible mistake. It makes it almost impossible to implement correctly, and to understand. But it's with us now in H98. -- Lennart
Jon Fairbairn wrote [snip]
Well, there's two things to consider: Haskell 98, which probably shouldn't change, and extended Haskell, which probably should. Especially if we can make the rules both simpler and better. [snip] How can I resist? I proposed the following revised layout rule some time ago in a message to the Twa Simons. Note that unlike the standard Haskell layout rules it does not need to read the parser's mind. Of course the problem is that while it should work fine for the way I lay out Haskell, it might not work for other people.
We represent the lines in a file in a tree like structure: data Grouped line = Grouped line [Grouped line] The meaning of Grouped A lines is a line A, followed by a list of groups, each beginning at the same deeper ind entation. So for example A B C D would go to something like Grouped A [Grouped B [Grouped C []],Grouped D []] In the code I've written A B C produces an error message, but on second thoughts I think the best behaviour wou ld be to treat it like A ++ B C though it's too late to code that now . . . The layout processor would group the lines according to this algorithm. It woul d then output the result of the grouping. When it came to Grouped first rest it would determine if the last token of first is "do", "of", "where" or "let", and rest does _not_ begin with a "{" token. If both these conditions were satis fied, it would output "{" before, ";" inbetween elements, and "}" after when outputting t he "rest" list. This seems to me to solve most of the fundamental problems, and be somewhat more intuitive than the existing algorithm. It would behave differently in that do if test then do act1 act2 else do act3 act4 is legal. But it would also be necessary to alter the context-free-syntax so th at (1) the contents of the module were not separated by ";"'s, but by each being a single item in the [Grouped line] list. (The old where {decl1 ; decl2 ; . . . ; decln} syntax would probably have to remain, for compatibility reasons). (2) single-line forms without braces, like "let a = 5 in a+a" work. This is only a first approximation, in that do if test then do act1 act2 else do act3 act4 isn't legal. Perhaps one way of fixing this is to modify the layout algorithm s o that tokens such as "then", "else", "in" and ")" before which a semicolon can't make any sense anyway, get tagged onto the previous group if that began at the same column as t hey did. I don't claim this as the perfect solution. But since layout is something which is rather confusing and at the moment seems to have distinctly rough edges, it might be wo rthwhile experimenting with something like this, to see how much code it would break
I wrote:
Can someone remind me why the "A close brace is also inserted whenever the syntactic category containing the layout list ends" part of the rule is there?
Lennart wrote:
It's so you can write let x = 2+2 in x*x (and similar things)
and Arjan van IJzendoorn wrote:
x = (3, case True of True -> 4)
The ')' ends the syntactic category 'tuple'
So we get all this misery just so that people can cram things onto fewer lines?
let x = 2+2 in x*x
could be
let {x = 2+2} in x*x
or
let x = 2+2 in x*x
and
x = (3, case True of True -> 4 )
would be fine. I'd like to see a "-fuse-simpler-layout-rule"¹ option on the compilers. . . Jón 1. Why "-f" anyway? It took me ages to work out what "-fallow-overlapping-instances" meant -- I wondered how "fallow" could apply to overlapping instances. -- Jón Fairbairn Jon.Fairbairn@cl.cam.ac.uk 31 Chalmers Road jf@cl.cam.ac.uk Cambridge CB1 3SZ +44 1223 570179 (after 14:00 only, please!)
Jon Fairbairn <Jon.Fairbairn@cl.cam.ac.uk> writes:
Why "-f" anyway? It took me ages to work out what "-fallow-overlapping-instances" meant -- I wondered how "fallow" could apply to overlapping instances.
I suppose it's a GCCism, where options starting with -f specifiy *f*lags. (Which doesn't seem to apply to GHC, unless there's a -fno-allow... (of -fdont-allow...?)) -kzm -- If I haven't seen further, it is by standing in the footprints of giants
participants (5)
-
Arjan van IJzendoorn -
George Russell -
Jon Fairbairn -
ketil@ii.uib.no -
Lennart Augustsson