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

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

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

Jeffrey Brown
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
Website   |   Facebook   |   LinkedIn(spammy, so I often miss messages here)   |   Github   

_______________________________________________
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.
Reply | Threaded
Open this post in threaded view
|

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

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 <[hidden email]>
> 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.
Reply | Threaded
Open this post in threaded view
|

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

Jeffrey 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 <[hidden email]> wrote:
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 <[hidden email]>
> 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   |   Facebook   |   LinkedIn(spammy, so I often miss messages here)   |   Github   

_______________________________________________
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.
Reply | Threaded
Open this post in threaded view
|

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

David Feuer
In reply to this post by Alexis King
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" <[hidden email]> wrote:
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 <[hidden email]>
> 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.

_______________________________________________
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.
Reply | Threaded
Open this post in threaded view
|

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

Alexis King
> On Sep 9, 2017, at 18:14, David Feuer <[hidden email]> 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.

_______________________________________________
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.