[Haskell-cafe] parametrized data types and Template Haskell

Maarten Faddegon haskell-cafe at maartenfaddegon.nl
Mon Dec 30 17:08:08 UTC 2013

Dear Cafe,

Thanks to the kind help of Adam and Richard I now can generate instances 
for parametrized data types with Template Haskell.

However, I still struggle adding class constraints to the type 
variables. I try to follow the derive_show example of Ian Lynagh but it 
seems some interfaces have changed since he wrote "Template Haskell: A 
Report From The Field".

I generate MyClass constraints for a set of type variables with the 
following code:

 > genCxt :: [TyVarBndr] -> Q Cxt
 > genCxt tvs = return [classp $ map (\v -> (tvname v)) tvs]
 > classp :: [Type] -> Pred
 > classp = ClassP (mkName "TH_playground.MyClass")
 > tvname :: TyVarBndr -> Type
 > tvname (PlainTV  name  ) = ConT name
 > tvname (KindedTV name _) = ConT name

To be able to generate MyClass instances with:

 > genInstance :: Q Type -> Q [Dec]
 > genInstance qt
 >   = do { t <- qt
 >        ; n <- case t of
 >              (ForallT tvs _ t') -> [t| MyClass $(return t') |]
 >              _                  -> [t| MyClass $qt |]
 >        ; m <- genMethod qt
 >        ; c <- case t of
 >                   (ForallT tvs _ t') -> genCxt tvs
 >                   _                  -> return []
 >        ; return [InstanceD c n m]
 >        }

Up to here, everything type checks and I can build the module where I 
defined it.
In a different module I try to generate an instance for MyData a:

 > data MyData a = MyCon a
 > $(genInstance [t| forall a.MyData a |])

This however does not seems to go down well with the compiler.

||     Illegal type constructor or class name: `a'
||     When splicing a TH declaration:
||       instance TH_playground.MyClass a_0 => TH_playground.MyClass 
(Main.MyData a_0)
||     where myMethod (Main.MyCon x_1) = "todo"

This error message confuses me because it seems to complain about the 
type variable a in the generate instance, but in the generated instance 
this variable is renamed to a_0. Also, when I copy the generated code 
from the error message the ghc is completely happy.

Without the class constraints the generated instance type checks and 
compiles as well:

 > genCxt _ = return []

But I would like to apply myMethod on the fields in parametrized data 
types, which is not correct without the class constraints.

Did I find a bug in ghc's Template Haskell implementation or am I doing 
something silly?



More information about the Haskell-Cafe mailing list