-- {-# LANGUAGE TemplateHaskell #-}
{-|
    Module      :  Utils.TH.DeclForTypes
    Description :  Repeat declaration for multiple types
    Copyright   :  (c) Michal Konecny
    License     :  BSD3

    Maintainer  :  mikkonecny@gmail.com
    Stability   :  experimental
    Portability :  portable

    Template Haskell utilities
-}

module Utils.TH.DeclForTypes
(
  declForTypes
)
where

import Prelude (concat, sequence, map, ($), Monad(..))

import Language.Haskell.TH

{- template haskell to generate repetitive instances -}

{-|

A toy example of use:

@
class HasTT t where
  type TT t
  getTT :: t -> TT t

$(declForTypes
  [[t| Integer |], [t| Int |], [t| Rational |]]
  (\ t -> [d|
    instance HasTT $t where
      type TT $t = ()
      getTT _ = ()
  |]))
@

-}
declForTypes :: [Q Type] -> (Q Type -> Q [Dec]) -> Q [Dec]
declForTypes :: [Q Type] -> (Q Type -> Q [Dec]) -> Q [Dec]
declForTypes [Q Type]
types Q Type -> Q [Dec]
makeDecl =
  do
  [[Dec]]
decsList <- [Q [Dec]] -> Q [[Dec]]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence ([Q [Dec]] -> Q [[Dec]]) -> [Q [Dec]] -> Q [[Dec]]
forall a b. (a -> b) -> a -> b
$ (Q Type -> Q [Dec]) -> [Q Type] -> [Q [Dec]]
forall a b. (a -> b) -> [a] -> [b]
map Q Type -> Q [Dec]
makeDecl [Q Type]
types
  [Dec] -> Q [Dec]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Dec] -> Q [Dec]) -> [Dec] -> Q [Dec]
forall a b. (a -> b) -> a -> b
$ [[Dec]] -> [Dec]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Dec]]
decsList