Is this a GHC parser error? A test case compiles from one line but not another.

The test suite below[1] does what it's supposed to. The last line of it is a commented-out test case: -- assertBool "broken" $ True If I uncomment that, it fails to compile: > :reload [13 of 13] Compiling TParse ( test/TParse.hs, interpreted ) test/TParse.hs:67:3: error: parse error on input ‘assertBool’ | 67 | assertBool "broken" $ True | ^^^^^^^^^^ Failed, 12 modules loaded. > However, if I move it to somewhere earlier in the code, it works. [1] https://github.com/JeffreyBenjaminBrown/digraphs-with-text/blob/e5afd39b9507... -- Jeff Brown | Jeffrey Benjamin Brown Website https://msu.edu/~brown202/ | Facebook https://www.facebook.com/mejeff.younotjeff | LinkedIn https://www.linkedin.com/in/jeffreybenjaminbrown(spammy, so I often miss messages here) | Github https://github.com/jeffreybenjaminbrown

No, it isn’t a GHC parser error. Your preceding expression ends in a where clause, like this: assertBool "4" $ p == Right a where p = ... That’s fine, but make sure you understand how where works. Where clauses are not attached to individual expressions, they are *always* attached to definitions. In this case, the where clause is not attached to the assertion but to your definition of tHash. GHC parses your program the same way as this one: tHash = TestCase $ do ... assertBool "4" $ p == Right a where p = ... Therefore, the where clause forces the termination of the do block, since it exists syntactically outside the “body” of a definition. It is its own syntactic construct, an optional sequence of definitions in scope within the RHS of a definition. You cannot have any more expression after the where clause because they would be free-floating, outside of any particular definition. If you really want definitions that are scoped to that single assertion, use a let expression instead of a where clause: let p = ... a = ... in assertBool "4" $ p == Right a That works, since let...in blocks serve as completely ordinary expressions, and they are permitted anywhere an expression is permitted (unlike where clauses, which must “belong” to a top-level or let-bound definition).
On Sep 8, 2017, at 20:54, Jeffrey Brown
wrote: The test suite below[1] does what it's supposed to. The last line of it is a commented-out test case:
-- assertBool "broken" $ True
If I uncomment that, it fails to compile:
> :reload [13 of 13] Compiling TParse ( test/TParse.hs, interpreted )
test/TParse.hs:67:3: error: parse error on input ‘assertBool’ | 67 | assertBool "broken" $ True | ^^^^^^^^^^ Failed, 12 modules loaded. >
However, if I move it to somewhere earlier in the code, it works.
[1] https://github.com/JeffreyBenjaminBrown/digraphs-with-text/blob/e5afd39b9507...
Jeff Brown | Jeffrey Benjamin Brown

Thanks, Alexis! Your explanation of the distinction between let and where
is the first I've understood.
On Fri, Sep 8, 2017 at 9:05 PM, Alexis King
No, it isn’t a GHC parser error.
Your preceding expression ends in a where clause, like this:
assertBool "4" $ p == Right a where p = ...
That’s fine, but make sure you understand how where works. Where clauses are not attached to individual expressions, they are *always* attached to definitions. In this case, the where clause is not attached to the assertion but to your definition of tHash. GHC parses your program the same way as this one:
tHash = TestCase $ do ... assertBool "4" $ p == Right a where p = ...
Therefore, the where clause forces the termination of the do block, since it exists syntactically outside the “body” of a definition. It is its own syntactic construct, an optional sequence of definitions in scope within the RHS of a definition. You cannot have any more expression after the where clause because they would be free-floating, outside of any particular definition.
If you really want definitions that are scoped to that single assertion, use a let expression instead of a where clause:
let p = ... a = ... in assertBool "4" $ p == Right a
That works, since let...in blocks serve as completely ordinary expressions, and they are permitted anywhere an expression is permitted (unlike where clauses, which must “belong” to a top-level or let-bound definition).
On Sep 8, 2017, at 20:54, Jeffrey Brown
wrote: The test suite below[1] does what it's supposed to. The last line of it is a commented-out test case:
-- assertBool "broken" $ True
If I uncomment that, it fails to compile:
> :reload [13 of 13] Compiling TParse ( test/TParse.hs, interpreted )
test/TParse.hs:67:3: error: parse error on input ‘assertBool’ | 67 | assertBool "broken" $ True | ^^^^^^^^^^ Failed, 12 modules loaded. >
However, if I move it to somewhere earlier in the code, it works.
[1] https://github.com/JeffreyBenjaminBrown/digraphs-with-text/blob/ e5afd39b950752ccb65997b89ab625d859299b4a/test/TParse.hs
Jeff Brown | Jeffrey Benjamin Brown
-- Jeff Brown | Jeffrey Benjamin Brown Website https://msu.edu/~brown202/ | Facebook https://www.facebook.com/mejeff.younotjeff | LinkedIn https://www.linkedin.com/in/jeffreybenjaminbrown(spammy, so I often miss messages here) | Github https://github.com/jeffreybenjaminbrown

Where clauses are not *always* attached to definitions. They can also be
attached to case branches.
case z of
Just n -> blah
where blah = n * 7
What I believe is true is that anywhere a set of guards could occur, they
may be followed by a where clause, and vice versa.
On Sep 9, 2017 12:08 AM, "Alexis King"
No, it isn’t a GHC parser error.
Your preceding expression ends in a where clause, like this:
assertBool "4" $ p == Right a where p = ...
That’s fine, but make sure you understand how where works. Where clauses are not attached to individual expressions, they are *always* attached to definitions. In this case, the where clause is not attached to the assertion but to your definition of tHash. GHC parses your program the same way as this one:
tHash = TestCase $ do ... assertBool "4" $ p == Right a where p = ...
Therefore, the where clause forces the termination of the do block, since it exists syntactically outside the “body” of a definition. It is its own syntactic construct, an optional sequence of definitions in scope within the RHS of a definition. You cannot have any more expression after the where clause because they would be free-floating, outside of any particular definition.
If you really want definitions that are scoped to that single assertion, use a let expression instead of a where clause:
let p = ... a = ... in assertBool "4" $ p == Right a
That works, since let...in blocks serve as completely ordinary expressions, and they are permitted anywhere an expression is permitted (unlike where clauses, which must “belong” to a top-level or let-bound definition).
On Sep 8, 2017, at 20:54, Jeffrey Brown
wrote: The test suite below[1] does what it's supposed to. The last line of it is a commented-out test case:
-- assertBool "broken" $ True
If I uncomment that, it fails to compile:
> :reload [13 of 13] Compiling TParse ( test/TParse.hs, interpreted )
test/TParse.hs:67:3: error: parse error on input ‘assertBool’ | 67 | assertBool "broken" $ True | ^^^^^^^^^^ Failed, 12 modules loaded. >
However, if I move it to somewhere earlier in the code, it works.
[1] https://github.com/JeffreyBenjaminBrown/digraphs-with-text/blob/ e5afd39b950752ccb65997b89ab625d859299b4a/test/TParse.hs
Jeff Brown | Jeffrey Benjamin Brown
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

On Sep 9, 2017, at 18:14, David Feuer
wrote: Where clauses are not *always* attached to definitions. They can also be attached to case branches.
Ah, you’re right of course, I forgot about this.
What I believe is true is that anywhere a set of guards could occur, they may be followed by a where clause, and vice versa.
This appears to be true in standard Haskell, but interestingly, it seems that where clauses *cannot* be attached to a multi-way if expression. Whether or not that counts as a “set of guards” is debatable, but I usually think of them that way, so it’s potentially worth nothing.
participants (3)
-
Alexis King
-
David Feuer
-
Jeffrey Brown