#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

Reply via email to