-- | The main TH driver module. It is intended that this need be the
-- only module imported by user code; it takes care of all data
-- threading issues such that all one needs to do is:
--
-- @
-- data Foo = Foo ; $( derive makeEq ''Foo )
-- @
module Data.DeriveTH(derive, derives, deriveFromDec, module Data.Derive.All) where
import Control.Monad
import Data.Derive.All
import Data.Derive.Internal.Derivation
import Language.Haskell.TH.All as TH hiding (Derivation(..),toName)
import Language.Haskell as HS
import Language.Haskell.Convert
-- | Derive an instance of some class. @derive@ only derives instances
-- for the type of the argument.
derive :: Derivation -> TH.Name -> Q [Dec]
derive d name = do
x <- reify name
case x of
TyConI dec -> deriveFromDec d dec
_ -> error $ "Data.DeriveTH.derive: Expected a data type declaration, got:\n" ++ show x
derives :: [Derivation] -> [TH.Name] -> Q [Dec]
derives xs ys = liftM concat $ sequence [derive x y | y <- ys, x <- xs]
-- | Derive an instance of some class. @deriveFromDec@ only derives instances
-- for the type of the argument.
deriveFromDec :: Derivation -> Dec -> Q [Dec]
deriveFromDec d x = do
x <- liftM normData $ expandData x
let unsup x = error $ "Derivation of " ++ derivationName d ++ " does not yet support Template Haskell, requires info for " ++ x
case derivationOp d (tyCon $ derivationName d) unsup $ toFullDataDecl x of
Left y -> runIO (putStrLn $ "Warning, couldn't derive: " ++ y) >> return []
Right v -> return $ convert v
toFullDataDecl :: Dec -> FullDataDecl
toFullDataDecl x = (ModuleName "Todo", convert x)