module Data.Constructors.TH (EqC(..),deriveEqC) where
import Data.Constructors.EqC
import Language.Haskell.TH as TH
import Language.Haskell.TH.Syntax as TH
deriveEqC :: Name -> DecsQ
deriveEqC n = do
(saturatedType,constructors) <- extractTypeCons n
return $
[InstanceD
Nothing
[]
(AppT (ConT ''EqC) saturatedType)
[FunD 'eqConstr constructors]]
extractTypeCons :: Name -> Q (TH.Type,[Clause])
extractTypeCons n = do
true <- lift True
false <- lift False
reify n <&> \case
TyConI (DataD _ _ tyVars _ cons _) ->
(foldl (\c -> AppT c . extractTV) (ConT n) tyVars
,foldr (\c acc -> Clause [RecP c [], RecP c []] (NormalB true) [] : acc)
[Clause [WildP,WildP] (NormalB false) []]
(map (\(NormalC n _) -> n) cons))
_ -> error "invalid name"
extractTV :: TyVarBndr -> TH.Type
extractTV = \case
PlainTV n -> VarT n
KindedTV n _ -> VarT n
(<&>) :: Functor f => f a -> (a -> b) -> f b
(<&>) = flip (<$>)