[Template-haskell] Binding again

Ian Lynagh igloo at earth.li
Thu Nov 25 13:41:42 EST 2004


On Thu, Nov 25, 2004 at 02:06:27PM -0000, Simon Peyton-Jones wrote:
> In looking into my TH bug stack, I've found the following question.

Here's what I think should happen:

> Suppose we have
> 
> d1 :: Q [Dec]
> d1 = return [FunD (mkName "f") ...]
> 
> d2 :: Q [Dec]
> d2 = do { fn <- newName "f"; return [FunD fn ...] }
> 
> QUESTION 1: is this OK:
> 
> 	$d1
> 	h = f 3
> 
> QUESTION 2: What about this?
> 
> 	$d2
> 	h = f 3
> 
> The answer to Q1 must presumably be 'yes',

Yes - mkName "f" gives you the same name as just writing f.

> but what about Q2.  "newName"
> generates a fresh name, to be sure, but does it bind the 'f' in the
> subsequent declaration.

No - here you have created a name that only looks a bit like f - it is
not the same as f. In fact, were you to pprint the above you should get
something like

    f_4 = ...
    h = f 3

The only way to refer to a newName is with the result of that call.

> I think the answer is probably 'yes'.  COnsier
> 	[| \x -> f $(dyn "x") |]

Here dyn calls mkName so you get the same name as would just writing x.
So it gets bound to that \x.

> Here I think we all agree the $(dyn "x") picks up the binding for 'x',
> even though the binding must be generated with newName. And (returning
> to Q2), the "top-level splice hack" treats everything following the
> top-level splice as if it were (dyn "f") stuff.

I don't think it should. If you did [d| f = ... |] then that should use
mkName, but if you explicitly construct something with newName then that
should be respected. After all, there is no gain for using newName if
you want to refer to it as f later, as you'd need to make sure there are
no name collisions so you may as well have just used mkName in the first
place. The only reason to use newName is /because/ you don't want it to
bind f (or to conflict with another newName).

> But a 'yes' to Q2 might be considered inconvenient, because you might
> generate lots of (newName "f"), and they'd then clash.

Indeed;

    $d1
    $d2

,

    $d2
    $d2

and

    $d2
    f = ...

should cause no name clashes, but both

    $d1
    $d1

and

    $d1
    f = ...

should.


Thanks
Ian



More information about the template-haskell mailing list