Failed OccName lookup in RnEnv with Template Haskell Hack

Clemens Fruhwirth clemens at
Thu Nov 2 08:11:31 EST 2006

I have written a set of function that generates hsSyn data structures,
in particular HsExpr. I want run these functions at compile time, so
it can generate user code. I do this via Template Haskell and an ugly
hack in TH. 

TcSplice.lhs expects an ExpQ monad as result for splice expressions. 
I hesitate to rewrite my functions to generate a TH.Exp hierarchy
instead of a (HsExpr RdrName) hierarchy. The hack is to extend TH.Exp
with a new constructor InternalE (HsExpr RdrName) and to add a pattern
to hsSyn/Convert.lhs in

ctvl :: TH.Exp -> CvtM (LHsExpr RdrName)
  cvt (InternalE expr) = return expr

This effectively percises the whole TH.Exp -> HsExpr conversion by
providing a Exp constructor with a HsExpr payload, and extending the
conversion to just unwrap this payload.

This enables me to hand HsExpr to the compiler via Template Haskell
via this elegant ugly hack: 

foobar = 
 $(return (InternalE <function that generates an HsExpr Tree))

Ok, are you still with me? Not running screaming? Fine.

The problem is that the RdrNames carried in the HsExpr are not found
in the Renamer environment. To give you an example

foobar =
 $(return (InternalE (HsVar (mkUnqual varName 
				      (mkFastString "myfoo")))))

which should in the overall result "foobar = myfoo"

Running this gives me a "Not in scope" error but the myfoo variable is
obviously in the global environment as running this with
-ddump-rn-trace shows:

    Not in scope: `myfoo{v}'
    Global envt is:
       myfoo{v}: main:MyAdd.myfoo{v rI9} imported from MyAdd at test.hs:13:20-24

In contrast, the TH variant works without any flaws:

 $(return (VarE (mkName "myfoo"))) 

I assert that the VarE variant and the InternalE variant are converted
to exactly the same HsExpr by hsSyn/Convert.lhs. Using -ddump-slices
-dppr-debug shows that both splices generate "myfoo{v}".

Using a few more hacks, I even made sure that the printed FastStrings
"myfoo" are equal in terms of "getKey# (getUnique str)", this pretty
much rules out a bug in UniqFM.hs.

Does anyone (especially the developers that are intimate with TH and
HsSyn) know what could be the cause? I spent twelve fruitless hours
searching for the cause.

Many thanks in advance,
Fruhwirth Clemens - 
for robots: sp4mtrap at

More information about the Glasgow-haskell-users mailing list