
It is with some hesitation that I want to bring up another point, in which Haskell' could be an improvement above Haskell: the offside rule. Although I manage to live with it, I encountered many problems with it in the past: 1) it is impossible to explain the precise workings of the rule to a class of first years undergraduates This is extremely demotivating. I do not want to teach using the following utterances: "If you write your programs in the same style as I do on my slides, you will usually get away with it". Students are perfectly happy to accept that complicated things are complicated, but are not very willing to buy complicated explanations for things which ought to be simple. I furthermore think it is waist of time to to have to go into this in my lectures. I do not think the alternative, in which you always have to write { ; ; } is an option. A language in which every let is followed by a { is plain stupid; just like in Pascal, where each procedure, function, const, var and begin keyword has to be preceded by a (thus superfluous) semicolon. 2) it has created havoc among students for years, with Hugs complaining about improper semicolons, whereas the student has not typed a single semicolon in his program. many students think Haskell is a complicated language, mainly because of offside rules, (and the monomorphism restriction of course) 3) it is formulated in an implementation oriented way, prohibiting proper tool support for parser generation With our parser combinator library we have created very efficient error-correcting parsers (far more efficient that Parsec based ones) for quite a few languages (including Haskell). Creating one for Haskell however became a nightmare, although we have managed to encapsulate the problem in a special offside parser combinator. Our parsers perform error-correction automatically, and this is simply not compatible with a prescription in the language definition as to how certain parse errors should be dealt with (especially that they are not errors). We had to put parser-brain-surgery into place in order to cope with the description of the offside rule. Although the problem is solved by the introduction of the offside combinator now, I think it is a sign of unhealthiness of the formulation, which is too implementation dependent. 4) based on many examples my claim is that almost no Haskell programmer can always correctly apply to offside rule We might go back to something simpler, like e.g. the Miranda(tm) rule, in which declarations have to start in the same column, and a declaration extends to the lower right of its first character. Doaitse Swierstra

On Wed, 8 Mar 2006, Doaitse Swierstra wrote:
1) it is impossible to explain the precise workings of the rule to a class of first years undergraduates
This is extremely demotivating. I do not want to teach using the following utterances: "If you write your programs in the same style as I do on my slides, you will usually get away with it". Students are perfectly happy to accept that complicated things are complicated, but are not very willing to buy complicated explanations for things which ought to be simple. I furthermore think it is waist of time to to have to go into this in my lectures. I do not think the alternative, in which you always have to write { ; ; } is an option. A language in which every let is followed by a { is plain stupid; just like in Pascal, where each procedure, function, const, var and begin keyword has to be preceded by a (thus superfluous) semicolon.
I found the layout rule trivial to understand the moment I knew about the braces-and-semicolons versions of the constructs and that the layout rule desugars to that with some simple rules. After that it was just a matter of remembering where the braces are on which constructs. I can see it might be a little harder explaining it to a class who haven't seen a braces-and-semicolons language before Haskell though. -- flippa@flippac.org 'In Ankh-Morpork even the shit have a street to itself... Truly this is a land of opportunity.' - Detritus, Men at Arms

Hi,
1) it is impossible to explain the precise workings of the rule to a class of first years undergraduates
Then don't explain it to them. At York in the 3rd year Haskell course it is never explained in detail, I think it might be briefly mentioned in passing that some kind of indentation thing is used, but not focused on. I certainly don't have a clue what the rule is. I believe the Haskell rule is a superset of the Miranda (TM) one? If so just explain the Miranda one. I have a friend, who was programming Haskell for 3 years before he even realised that the indentation had an effect on the program! And not trivial stuff, he wrote a lot of big programs. If you just do sensible indentation, then it just works (TM). As for hugs complaining about semi-colons, thats just a bad error message - not a reason for a language change. Of course, your point about being overly complex is possibly true - but I don't think its possible to reduce the complexity without breaking existing programs, and I don't think its worth doing that. The one thing about having the offside rule which bugs me is that some people use tabs with 8 spaces (Haskell standard), others use 4 (me) and others use variable other sizes. This makes code 100% incompatible between different people. I would make it a warning to use a tab in a Haskell source file. Thanks Neil

Neil,
1) it is impossible to explain the precise workings of the rule to a class of first years undergraduates
Then don't explain it to them. At York in the 3rd year Haskell course it is never explained in detail, I think it might be briefly mentioned in passing that some kind of indentation thing is used, but not focused on. I certainly don't have a clue what the rule is.
Well, that of course only works out well if students don't violate the offside rule. As soon as they do (for instance, because they use tabs instead of spaces to lay out their code), they want to know why the compiler rejects their programs. For students that have the right attitude, you can't just say that "it has something to do with indentation" then, because those will want to know the details then. Regards, Stefan

1) it is impossible to explain the precise workings of the rule to a class of first years undergraduates
Try "Python copied the offside rule from Haskell, so it must be cool." (*) http://docs.python.org/ref/indentation.html Which is true only "morally", e. g. it says here http://www.python.org/doc/faq/general.html#what-is-python that the indentation idea comes from a language ABC: http://homepages.cwi.nl/~steven/abc/ Where does Haskell's rule come come from? (*) Of course the typical undergrad is a part-time web developer, using Zope, and he thinks that Python is cool because it has no static typing, so that programming is "much easier" than at university where they teach him Haskell. But he soon finds that he can leave out all Haskell type signatures as well, so he thinks that Haskell is going in the right direction... -- -- Johannes Waldmann -- Tel/Fax (0341) 3076 6479/80 -- ---- http://www.imn.htwk-leipzig.de/~waldmann/ -------

I agree with it being complicated. I don't know of any compiler that implements it correctly. Do you say your combinators do? That said, I don't think it can be replaced easily without breaking existing code, so I'm unwilling to change unless someone can show an alternative that handles 99.9% of the existing code. -- Lennart Doaitse Swierstra wrote:
It is with some hesitation that I want to bring up another point, in which Haskell' could be an improvement above Haskell: the offside rule.
Although I manage to live with it, I encountered many problems with it in the past:
1) it is impossible to explain the precise workings of the rule to a class of first years undergraduates
This is extremely demotivating. I do not want to teach using the following utterances: "If you write your programs in the same style as I do on my slides, you will usually get away with it". Students are perfectly happy to accept that complicated things are complicated, but are not very willing to buy complicated explanations for things which ought to be simple. I furthermore think it is waist of time to to have to go into this in my lectures. I do not think the alternative, in which you always have to write { ; ; } is an option. A language in which every let is followed by a { is plain stupid; just like in Pascal, where each procedure, function, const, var and begin keyword has to be preceded by a (thus superfluous) semicolon.
2) it has created havoc among students for years, with Hugs complaining about improper semicolons, whereas the student has not typed a single semicolon in his program. many students think Haskell is a complicated language, mainly because of offside rules, (and the monomorphism restriction of course)
3) it is formulated in an implementation oriented way, prohibiting proper tool support for parser generation
With our parser combinator library we have created very efficient error-correcting parsers (far more efficient that Parsec based ones) for quite a few languages (including Haskell). Creating one for Haskell however became a nightmare, although we have managed to encapsulate the problem in a special offside parser combinator. Our parsers perform error-correction automatically, and this is simply not compatible with a prescription in the language definition as to how certain parse errors should be dealt with (especially that they are not errors). We had to put parser-brain-surgery into place in order to cope with the description of the offside rule. Although the problem is solved by the introduction of the offside combinator now, I think it is a sign of unhealthiness of the formulation, which is too implementation dependent.
4) based on many examples my claim is that almost no Haskell programmer can always correctly apply to offside rule
We might go back to something simpler, like e.g. the Miranda(tm) rule, in which declarations have to start in the same column, and a declaration extends to the lower right of its first character.
Doaitse Swierstra
_______________________________________________ Haskell-prime mailing list Haskell-prime@haskell.org http://haskell.org/mailman/listinfo/haskell-prime

On 2006 mrt 09, at 1:54, Lennart Augustsson wrote:
I agree with it being complicated. I don't know of any compiler that implements it correctly. Do you say your combinators do?
At least we think so. The way to use it is e.g.: pExprPrefix = sem_Expr_Let <$ pKey "let" <*> pDecls <* pKey "in" pDecls = foldr sem_Decls_Cons sem_Decls_Nil <$> pBlock pOCurly pSemi pCCurly pDecl pDecl = sem_Decl_Val <$> pPatExprBase <* pKey "=" <*> pExpr <|> sem_Decl_TySig <$> pVar <* pKey "::" <*> pTyExpr in which the pBlock takes care of the offside rule, in cooperation with the scanner.
That said, I don't think it can be replaced easily without breaking existing code, so I'm unwilling to change unless someone can show an alternative that handles 99.9% of the existing code.
There are solutions to this kind of transitions. Compilers could admit the old rule, and emit a warning when e.g. the --this-is- supposed-to-be-strictly-haskell-prime flag is passed. One might also equip a compiler to transform one's program into the new standard. Doaitse

If you can parse "do x == y == z" or "case 0 of x -> x == x == True" you're probably ok. I can't tell from your example if this works or not. -- Lennart Doaitse Swierstra wrote:
On 2006 mrt 09, at 1:54, Lennart Augustsson wrote:
I agree with it being complicated. I don't know of any compiler that implements it correctly. Do you say your combinators do?
At least we think so. The way to use it is e.g.:
pExprPrefix = sem_Expr_Let <$ pKey "let" <*> pDecls <* pKey "in"
pDecls = foldr sem_Decls_Cons sem_Decls_Nil <$> pBlock pOCurly pSemi pCCurly pDecl
pDecl = sem_Decl_Val <$> pPatExprBase <* pKey "=" <*> pExpr <|> sem_Decl_TySig <$> pVar <* pKey "::" <*> pTyExpr
in which the pBlock takes care of the offside rule, in cooperation with the scanner.
That said, I don't think it can be replaced easily without breaking existing code, so I'm unwilling to change unless someone can show an alternative that handles 99.9% of the existing code.
There are solutions to this kind of transitions. Compilers could admit the old rule, and emit a warning when e.g. the --this-is-supposed-to-be-strictly-haskell-prime flag is passed. One might also equip a compiler to transform one's program into the new standard.
Doaitse

On Wed, Mar 08, 2006 at 10:27:48PM +0100, Doaitse Swierstra wrote:
It is with some hesitation that I want to bring up another point, in which Haskell' could be an improvement above Haskell: the offside rule.
This is something I would have brought up too, except I don't think I'll have time to look into it properly in the advertised timescale. I conjecture that with a suitable set of bracketing keywords and symbols (if/then, let/in, [/], ...) the "parse error => close implicit block" rule could be dropped without significantly altering the set of acceptable programs (just rejecting programs that people really oughtn't be writing anyway (IMNSHO), like Lennart's examples). Things are slightly complicated by things like [ ... | ... ] and "let" not always being closed by "in" (so you just have to have it implicitly closed when you want to insert a ; in a "do" block), but I haven't thought of anything that'll actually break it. Then again, I haven't thought too hard about it or tried it out yet. I'm not sure how much easier this will make it to explain the rule to people - if you just explain the gist using the simple examples of bracketing, like if/then, then I think it would be significantly simpler, but if you'd want to explain all the niggly details then it might end up also being too complex. The main advantage is it would make layout a separate pass between lexical analysis and parsing. Thanks Ian
participants (7)
-
Doaitse Swierstra
-
Ian Lynagh
-
Johannes Waldmann
-
Lennart Augustsson
-
Neil Mitchell
-
Philippa Cowderoy
-
Stefan Holdermans