Can Template Haskell generate multi-param typeclass instances?

haskell, template-haskell

Solution

Yes, multi-parameter type classes are supported.

Somewhat confusingly, the `Type` argument refers to the entire instance head, and, even though it's not really a type, it looks enough like one syntactically that the type `Type` was reused for this purpose.

Therefore, if you're generating a multi-parameter `instance Foo Int Bool`, you need to use the "type" `Foo Int Bool`, constructed for example like this:

(ConT (mkName "Foo") `AppT` ConT (mkName "Int")) `AppT` ConT (mkName "Bool")

Here's a complete example:

{-# LANGUAGE MultiParamTypeClasses, TemplateHaskell #-}

import Language.Haskell.TH

class Foo a b where
  foo :: (a, b)

$(return [InstanceD [] (((ConT (mkName "Foo")) `AppT` ConT (mkName "Int")) `AppT` ConT (mkName "Bool"))
   [ValD (VarP (mkName "foo")) 
         (NormalB (TupE [LitE (IntegerL 42), ConE (mkName "False")])) []]])

main = print (foo :: (Int, Bool))

Problem

The latest (2.8.0.0) definition for the `Dec` has the following instance constructor: ``` InstanceD Cxt Type [Dec] ``` Seems that only one type can be instantiated. Is there a way to work around this?

Original source