#5398: Multiple declarations of uniquely generated name
---------------------------------+------------------------------------------
Reporter: basvandijk | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Template Haskell | Version: 7.0.4
Keywords: | Testcase:
Blockedby: | Difficulty:
Os: Unknown/Multiple | Blocking:
Architecture: Unknown/Multiple | Failure: None/Unknown
---------------------------------+------------------------------------------
Comment(by simonpj):
Sigh. See #5375, especially the first comment in the sequence.
I can see that what you want is reinerp's "totally fresh" semantics, and I
can see why: the functions you need are local to that particular splice,
and will never be referenced outside it.
I'm beginning to wonder whether I should recant on #5037. That is, perhaps
#5037 wasn't a bug at all, and I was too eager to "fix" it.
To reprise, the issue is this. Consider
{{{
foo = True
bar1 = $([| \foo -> $( return (VarE 'foo)) |])
bar2 = $(do { foo <- newName "foo"
; return (LamE (VarP foo) (VarE foo)) })
-- Both expand to (\foo -> foo)
bar3 = $([| \foo -> $( return (VarE (mkName "foo") ) |])
bar4 = $(do { foo <- newName "foo"
; return (LamE (VarP foo) (VarE (mkName "foo"))) })
}}}
Here, `bar1` and `bar2` do the same thing; its just that `bar` uses
quotation syntax to generate the lambda and the fresh name, whereas `bar2`
does the same thing by steam using `newName`.
But what about `bar3` and `bar4`? Again they are equivalant, except that
`bar4` does things by steam. But:
* PLAN A: They generate `(\foo34 -> foo)`, where the body of the lambda
binds to the top-level `foo`? That is, the `(mkName "foo")` is not
captured by a binding of a variable built with `newName`.
* PLAN B: They generate `(\foo -> foo)`, where the "foo" variable in the
body of the lambda is captured by the lambda-binding.
GHC 7.0 picked PLAN A. #5037 said that was a bug: the `(mkName "foo")`
should be captured by a variable generated with `newName`. So GHC 7.2
uses PLAN B.
A consequence of PLAN B is that this won't work:
{{{
$[| x = True |]
$(do { y <- newName "y"
; return [FunD y [...clause for True....]] })
-- Under Plan B, both generate something like x34 = True, y39 = True
z1 = x -- x not in scope
z2 = y -- y not in scope
}}}
You could make this work by using `mkName "x"` for the binders, but that
is unreasonably clumsy. (Incidentally this ''did'' work in GHC 7.0, but
only because of a HACK (using `mkName` rather than `newName` when
desugaring top-level bindiner in declaration quotes; not only was this a
grevious hack, but it cuased a bug: #5379.)
I'm having trouble seeing a good path through this thicket. Maybe someone
less buried in details can help. Interested parties please comment.
Examples are useful.
Simon
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/5398#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs