I have the following declaration:
class Indices xs where
type Index xs :: Type
type Value xs :: Type
{- ... -}
I want to write TemplateHaskell to generate the following pattern:
instance Indices (x, x) where
type Index (x, x) = Integer
type Value (x, x) = x
{- ... -}
instance Indices (x, x, x) where
type Index (x, x, x) = Integer
type Value (x, x, x) = x
{- ... -}
However, I cannot find a way to generate the type synonym declarations.
instanceIndices :: Int -> Q Dec
instanceIndices n = do
let
-- @'generate' 2 "x" f@ generates the list @[f 0 "x", f 1 "x", f 2 "x"]@.
generate :: Int -> [Char] -> (Int -> [Char] -> Q Type) -> [Q Type]
generate n prefix n_p_qt = fmap (`n_p_qt` prefix) [0 .. n]
instanceD
(pure [])
( appT
(conT (mkName "Indices"))
( foldl'
appT
(tupleT (n + 1))
(generate n "x" \_ pfx -> varT (mkName pfx))
)
)
[ tySynD
(mkName "Index")
[plainTV (mkName "_")]
(conT (mkName "Integer"))
, tySynD
(mkName "Value")
[plainTV (mkName "_")]
(conT (mkName "x"))
]
Then $(instanceIndices 0) generates the declaration
instance Indices (Solo x) where
type Index _ = Integer
type Value _ = x
-- GHC-23882
-- Illegal declarations in an instance declaration:
-- type Index _ = Integer
-- type Value _ = x