Skip to content

Template Haskell top level scoping error

Consider this

module TH where

  $( [d| x = True; f1 = x |])

  $( [d| x = 'c'; f2 = x |] )

I think this should compile fine. There are two bindings of x, so I would not expect to be able to name x in the export list, or indeed anywhere else. But x may just be a local helper-function to the other bindings (f1 and f2 resp) so that's fine.

Alas I get

~/5builds/HEAD-4/inplace/bin/ghc-stage2 -c TH.hs -ddump-splices -ddump-tc
TH.hs:5:4-26: Splicing declarations
    [d| x_apA = True
        f1_apB = x_apA |]
  ======>
    x_a3tN = True
    f1_a3tO = x_a3tN
TH.hs:7:4-25: Splicing declarations
    [d| x_a3u4 = 'c'
        f2_a3u5 = x_a3u4 |]
  ======>
    x_a3uW = 'c'
    f2_a3uX = x_a3uW

TH.hs:7:4: error:
    Multiple declarations of ‘x’
    Declared at: TH.hs:5:4
                 TH.hs:7:4

TH.hs:7:4: error:
    The exact Name ‘x_a3uW’ is not in scope
      Probable cause: you used a unique Template Haskell name (NameU), 
      perhaps via newName, but did not bind it
      If that's it, then -ddump-splices might be useful

So:

  • Perhaps we should not complain about multiple top-level bindings for x if they are all Exact RdrNames.
  • And the "not in scope" message is clearly bogus.

Mind you, would you expect this to work?

x = True

$( [d| x = 'c'; f2 = x |] )

foo = x  -- Which 'x' do we get?

Maybe the occurrence of x in foo is ambiguous. If you want to splice a hidden helper binding, which can't clash with some earlier or later user-supplied thing, then use an occurrence like $x.

Trac metadata
Trac field Value
Version 8.0.1
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Template Haskell
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information