Details

This implements -XDeriveLift, which allows for automatic derivation
of the Lift class from template-haskell. The implementation is based
off of Ian Lynagh's th-lift library
(http://hackage.haskell.org/package/th-lift).

How should primitive data types be handled? I adapted the approach Show takes, which has special cases for Char#, Float#, Double#, Int#, and Word#. Note that template-haskell also has a StringPrimL constructor, so we could handle Addr# as well, but there's not currently a function of type String -> [Word8] in base that I could use in conjunction with it (there is in ghc, but I'm not sure if it's verboten to put GHC internals in derived code).

What should we do if someone attempts to derive Lift on a datatype with no constructors?

My weakly held opinion is this should be a splice-time error.

How should primitive data types be handled? I adapted the approach Show takes, which has special cases for Char#, Float#, Double#, Int#, and Word#.

This sounds reasonable to me.

Note that template-haskell also has a StringPrimL constructor, so we could handle Addr# as well, but there's not currently a function of type String -> [Word8] in base that I could use in conjunction with it (there is in ghc, but I'm not sure if it's verboten to put GHC internals in derived code).

Does map (fromIntegral . Data.Char.ord) not do the trick? That's all SMRep.stringToWord8s does.

Deriving Lift for a constructor-less datatype now results in code which will yield an error at splice-time (I will try to coordinate with @osa1 so that it is handled uniformly alongside other language extensions in D978).

I expanded the documentation for how Lift works in the users' guide, and I included a little Haddock snippet for the Lift typeclass as well.

It's nice to document all this. Perhaps include this fun fact: If GHC sees [| foo bar |], it looks up each name. If the name is global, the fully qualified name is used in the quotation, and any splicing code does not even need to import that identifier. If the name is local (say bar is local), then GHC uses lift, pretending that the code contains [| foo $(lift bar) |]. Thus the bar, which may not be in scope at splice locations, is actually evaluated when the quotation is processed. The use of lift here requires that a Lift instance be available.

The comment about deriving Lift for an empty datatype was actually outdated, since I changed it to code that results in a splice-time error as per Ben and Reid's suggestions. I believe that the behavior for deriving classes on empty datatypes is going to change sometime in the future, so I'll defer any changes to that particular endeavor.

The upshot is that GHC HEAD already reports a source location whenever a TH splice fails, so I can fulfill half of your request :)

Also, could you open a pull request against Cabal with the relevant changes?

I made the error message a bit more descriptive in the interim—it now tells you the type constructor of the empty datatype à laderiving Generic. I think that the deriving behavior for empty datatypes is bound to change eventually, though.