Fails with multiple binders in let-in in do-notation #290

Open
opened 2020-04-02 16:25:00 +02:00 by tfausak · 2 comments
tfausak commented 2020-04-02 16:25:00 +02:00 (Migrated from github.com)

Given the following input:

main = do let { one = 1; two = 2 } in print ( one + two )

Brittany (version 0.12.1.1) fails and produces this output:

ERROR: brittany pretty printer returned syntactically invalid result.
main = do
  let one = 1
      two = 2
  in  print (one + two)

If there's only one binder in the let and it's short enough, Brittany produces output that works:

-- input
main = do let { one = 1 } in print one
-- output
main = do
  let one = 1 in print one

GHC is fine with let ... in ... inside do notation as long as everything after the let is indented enough. It's possible to format the first example using layout like so:

main = do
  let
    one = 1
    two = 2
    in print ( one + two )
Given the following input: ``` hs main = do let { one = 1; two = 2 } in print ( one + two ) ``` Brittany (version 0.12.1.1) fails and produces this output: ``` hs ERROR: brittany pretty printer returned syntactically invalid result. main = do let one = 1 two = 2 in print (one + two) ``` If there's only one binder in the `let` and it's short enough, Brittany produces output that works: ``` hs -- input main = do let { one = 1 } in print one -- output main = do let one = 1 in print one ``` GHC is fine with `let ... in ...` inside `do` notation as long as everything after the `let` is indented enough. It's possible to format the first example using layout like so: ``` hs main = do let one = 1 two = 2 in print ( one + two ) ```
lspitzner commented 2020-04-06 19:44:13 +02:00 (Migrated from github.com)

Thanks for the report, need to keep track of this.

I have thought about this briefly before, and I thought we'd be able to transform it into do's variant of let (the one without in). But that does not work in general, because you can have recursive bindings:

main = do
  let { x = 1 : y ; y = 2 : x } in print (take 10 x)
-- perfectly valid but
main = do
  let x = 1 : y -- kaboom
  let y = 1 : x
  print (take 10 x)

So your last suggestion is the only working solution I think.

Thanks for the report, need to keep track of this. I have thought about this briefly before, and I _thought_ we'd be able to transform it into `do`'s variant of `let` (the one without `in`). But that does not work in general, because you can have recursive bindings: ~~~~.hs main = do let { x = 1 : y ; y = 2 : x } in print (take 10 x) -- perfectly valid but main = do let x = 1 : y -- kaboom let y = 1 : x print (take 10 x) ~~~~ So your last suggestion is the only working solution I think.
tfausak commented 2020-04-06 20:43:35 +02:00 (Migrated from github.com)

Alternatively you may be able to drop the in, although that might lead to weird scoping problems.

main = do
  let one = 1
      two = 2
  print ( one + two )
Alternatively you may be able to drop the `in`, although that might lead to weird scoping problems. ``` hs main = do let one = 1 two = 2 print ( one + two ) ```
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: hexagoxel/brittany#290
There is no content yet.