Call to arms: lambda-case is stuck and needs your help
Tyson Whitehead
twhitehead at gmail.com
Sat Jul 7 06:08:26 CEST 2012
On July 6, 2012 11:49:23 Tyson Whitehead wrote:
> Currently it depends on the depth of this new level of indentation relative
> to all the groupings started on that line. I think most people would
> expect it to just apply to the last grouping though. That is
>
> where { f x = do {
> stmt1
> stmt2
> } }
>
> mask $ let { x = do {
> stmt1
> stmt2
> } }
>
> The rule in this case would be that if the grouping began on a newline that
> is idented farther then the previous line, the grouping is assocated with
> the grouping token and when it closes, it closes all those deeper than
> itself.
I've thought some more about this and it seems to me that there are two ways
people might intuitively think about doing grouping via indentation.
1 - the first item is on the same line and subsequent ones are lined up with it
do stmt1
stmt2
2 - the first item is on a new line and subsequent ones are lined up with it.
do
stmt1
stmt2
The current layout engine is targeted at (1). It appears to do (2), but it is
not really reliable as things start to go south if the first line happened to
open more than one grouping (precisely the problem that make '\' a group token
would introduce in codes). For an example, consider
let greet name = do
putStr "hello "
putStrLn name
in f "world"
It currently translates into
let { greet name = do {} } putStr "hello " putStrLn name in f "world"
This results in an unituituve "Empty 'do' construct" error message.
I propose we detected (2) and make it work too. That is, if the line ends
with a grouping construct and the next line is indented relative to that line,
then assume we really don't want '{}' and instead always start grouping (even
if it isn't indented further than other possible groupings also started).
In other words, translate the above into
let { greet name = do {
putStr "hello";
putStrLn name
}} in f "world"
This would then correctly handle the problamatic case raised in wiki where
mask $ \restore -> do
stmt1
stmt2
is in translated into
mask $ \ { restore -> do {} } stmt1 stmt2
under the current rules if '\' is made a grouping token.
The very limited scope of this (i.e., it would only apply to lines that end
with a grouping construct where the next line is indented further than that
line) should also address Simon's concerns regarding things like
f x y = x + y
where -- I just left this where here by accident
g x = ...
and
instance Exception Foo where
instance Exception Bar
Cheers! -Tyson
PS: To be fully precise, the modified layout decoder in 9.3 would be
L (<n>:ts) i (m:ms) = ; : (L ts n (m:ms)) if m = n
= } : (L (<n>:ts) n ms) if n < m
L (<n>:ts) i ms = L ts n ms
L ({n}:<n>:ts) i ms = { : (L ts n (n:ms)) if n > i (new rule)
L ({n}:ts) i (m:ms) = { : (L ts i (n:m:ms)) if n > m (Note 1)
L ({n}:ts) i [] = { : (L ts i [n]) if n > 0 (Note 1)
L ({n}:ts) i ms = { : } : (L (<n>:ts) i ms) (Note 2)
L (}:ts) i (0:ms) = } : (L ts i ms) (Note 3)
L (}:ts) i ms = parse-error (Note 3)
L ({:ts) i ms = { : (L ts i (0:ms)) (Note 4)
L (t:ts) i (m:ms) = } : (L (t:ts) i ms) if m /= 0 and parse-error(t)
(Note 5)
L (t:ts) i ms = t : (L ts i ms)
L [] i [] = []
L [] i (m:ms) = } : L [] i ms if m /= 0 (Note 6)
http://www.haskell.org/onlinereport/syntax-iso.html
As before, the function 'L' maps a layout-sensitive augmented token stream to
a non-layout-sensitive token stream, where the augmented token stream includes
'<n>' and '{n}' to, respectively, give the indentation level of the first token
on a new line and that following a grouping token not followed by '{'.
This time though, we allow the '{n}' '<n>' sequence (before it was supressed
to just '{n}'). We also add a new state variable 'i' to track the indentation
of the current line. The new rule now opens a grouping over a newline so
long as the indentation is greater than the current line.
Upon a less indented line, it will then close all currently open groups with
an indentation less than the new line.
More information about the Glasgow-haskell-users
mailing list