[Haskell-cafe] parametrized data types and Template Haskell

adam vogt vogt.adam at gmail.com
Thu Dec 26 18:56:42 UTC 2013

Hello Maarten,

You might also accept a string "Tree a" and then parse it as a Type by
use of haskell-src-meta's parseType. Then you'll have to search
through the Type data to get all the type variables, which might be
tricky in the general case.

Easier for you would be to require users to specify their type as:

  [t| forall a. Tree a |]

This gives a data structure that looks like:

  ForallT [PlainTV a_16] [] (AppT (ConT Data.Tree.Tree) (VarT a_16))

Which I found by typing this into ghci: $([t| forall a. Tree a |] >>=
stringE . show)

The ForallT has all the pieces to generate the whole instance declaration:

genMyClassInstance' :: Type -> Q Dec
genMyClassInstance' (ForallT tvs _ ty) =
    (sequence [ classP ''MyClass [varT t] | PlainTV t <- tvs ])
    [t| MyClass $(return ty) |]
    [funD 'myMethod [clause
                        (normalB [| "todo" |])
                        []] ]

It often doesn't work to use [| |] quotes everywhere. So you have to
use the functions/constructors in the Language.Haskell.TH module to
make it yourself. That doesn't rule out being able to use those quotes
as arguments to those functions (as you see above).

Finally the use of genMyClassInstance' looks like:

fmap return . genMyClassInstance' =<< [t| forall a. Tree a |]

Which can be mostly hidden in another function to define which might
be called "genMyClassInstance".


More information about the Haskell-Cafe mailing list