indentation with let and do
Hi the list, why do this function doesn't compile (parse error): test :: Bool -> IO () test foo = do let bar = case foo of True -> "Foo"; False -> "Bar" return () while this one does (just adding one space in front of True and False): test :: Bool -> IO () test foo = do let bar = case foo of True -> "Foo"; False -> "Bar" return () Thanks!! Corentin
The first version has bar True and False all at the same indentation level. As such they are seen as standalone expressions, rather than being nested under the one introduced by bar. See http://en.wikibooks.org/wiki/Haskell/Indentation On Thu, Oct 3, 2013 at 8:31 PM, Corentin Dupont <corentin.dupont@gmail.com>wrote:
Hi the list, why do this function doesn't compile (parse error):
test :: Bool -> IO () test foo = do let bar = case foo of True -> "Foo"; False -> "Bar" return ()
while this one does (just adding one space in front of True and False):
test :: Bool -> IO () test foo = do let bar = case foo of True -> "Foo"; False -> "Bar" return ()
Thanks!! Corentin
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
On Thu, Oct 3, 2013 at 2:31 PM, Corentin Dupont <corentin.dupont@gmail.com>wrote:
test :: Bool -> IO () test foo = do let bar = case foo of True -> "Foo"; False -> "Bar" return ()
while this one does (just adding one space in front of True and False):
test :: Bool -> IO () test foo = do let bar = case foo of True -> "Foo"; False -> "Bar" return ()
Do you understand how layout works? Informally, something that is more indented is a continuation of the previous expression, while something equally or less indented is a new expression. In this case, the previous expression is `bar = case foo of` and indenting `True` to the same level as `bar` means you have ended the expression starting with `bar =`. Adding just one extra space indicates that it's still part of `bar =`. (ghc is actually being somewhat lenient here; strictly speaking, you are not indented beyond the `case` so it should have ended the `case` expression. ghc allows some sloppiness like this when there absolutely must be something else after, but there are limits mostly imposed by layout introducers like `let` and `do`.) -- brandon s allbery kf8nh sine nomine associates allbery.b@gmail.com ballbery@sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net
On Thu, Oct 3, 2013 at 9:44 PM, Brandon Allbery <allbery.b@gmail.com> wrote:
On Thu, Oct 3, 2013 at 2:31 PM, Corentin Dupont <corentin.dupont@gmail.com
wrote:
test :: Bool -> IO () test foo = do let bar = case foo of True -> "Foo"; False -> "Bar" return ()
while this one does (just adding one space in front of True and False):
test :: Bool -> IO () test foo = do let bar = case foo of True -> "Foo"; False -> "Bar" return ()
Do you understand how layout works? Informally, something that is more indented is a continuation of the previous expression, while something equally or less indented is a new expression. In this case, the previous expression is `bar = case foo of` and indenting `True` to the same level as `bar` means you have ended the expression starting with `bar =`. Adding just one extra space indicates that it's still part of `bar =`.
(ghc is actually being somewhat lenient here; strictly speaking, you are not indented beyond the `case` so it should have ended the `case` expression. ghc allows some sloppiness like this when there absolutely must be something else after, but there are limits mostly imposed by layout introducers like `let` and `do`.)
Brandon, Indentation of 'case' itself doesn't matter. The layout is introduced by 'of', and then it's the indentation of the lexeme which follows 'of' that matters. So GHC is correct here. Roman
Thanks to all for your replies! I asked the question because I often make this kind of transformations (please don't mind the non-sensical example): test :: Bool -> IO () test foo = do bar <- case foo of True -> return "Foo" False -> return "Bar" return () into test :: Bool -> IO () test foo = do let bar = case foo of True -> "Foo" False -> "Bar" return () And was wondering why can't I maintain the initial (and nicer) indentation. But since let allows for several bindings, it make sense... Best, Corentin On Thu, Oct 3, 2013 at 8:31 PM, Corentin Dupont <corentin.dupont@gmail.com>wrote:
test :: Bool -> IO () test foo = do let bar = case foo of True -> "Foo"; False -> "Bar" return ()
Imagine if bar was a toplevel function bar = case foo of True -> " Foo"; False -> "Bar"; Keep in mind that indentation level starts at the function name, not at the let keyword. On Thu, Oct 3, 2013 at 2:31 PM, Corentin Dupont <corentin.dupont@gmail.com>wrote:
Hi the list, why do this function doesn't compile (parse error):
test :: Bool -> IO () test foo = do let bar = case foo of True -> "Foo"; False -> "Bar" return ()
while this one does (just adding one space in front of True and False):
test :: Bool -> IO () test foo = do let bar = case foo of True -> "Foo"; False -> "Bar" return ()
Thanks!! Corentin
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (5)
-
AlanKim Zimmerman -
Brandon Allbery -
Corentin Dupont -
David McBride -
Roman Cheplyaka