-- | This module exports the templates for automatic instance deriving of "Transformation.Shallow" type classes. The most
-- common way to use it would be
--
-- > import qualified Transformation.Shallow.TH
-- > data MyDataType f' f = ...
-- > $(Transformation.Shallow.TH.deriveFunctor ''MyDataType)
--

{-# Language TemplateHaskell #-}
-- Adapted from https://wiki.haskell.org/A_practical_Template_Haskell_Tutorial

module Transformation.Shallow.TH (deriveAll, deriveFunctor, deriveFoldable, deriveTraversable)
where

import Control.Applicative (liftA2)
import Control.Monad (replicateM)
import Data.Functor.Compose (Compose(getCompose))
import Data.Functor.Const (Const(getConst))
import Data.Maybe (fromMaybe)
import Data.Monoid (Monoid, (<>))
import Language.Haskell.TH
import Language.Haskell.TH.Syntax (BangType, VarBangType, getQ, putQ)

import qualified Transformation
import qualified Transformation.Shallow
import qualified Rank2.TH


data Deriving = Deriving { Deriving -> Name
_constructor :: Name, Deriving -> Name
_variable :: Name }

deriveAll :: Name -> Q [Dec]
deriveAll :: Name -> Q [Dec]
deriveAll Name
ty = ((Name -> Q [Dec]) -> Q [Dec] -> Q [Dec])
-> Q [Dec] -> [Name -> Q [Dec]] -> Q [Dec]
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (Name -> Q [Dec]) -> Q [Dec] -> Q [Dec]
forall (f :: * -> *) b.
(Applicative f, Semigroup b) =>
(Name -> f b) -> f b -> f b
f ([Dec] -> Q [Dec]
forall (f :: * -> *) a. Applicative f => a -> f a
pure []) [Name -> Q [Dec]
deriveFunctor, Name -> Q [Dec]
deriveFoldable, Name -> Q [Dec]
deriveTraversable]
   where f :: (Name -> f b) -> f b -> f b
f Name -> f b
derive f b
rest = b -> b -> b
forall a. Semigroup a => a -> a -> a
(<>) (b -> b -> b) -> f b -> f (b -> b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Name -> f b
derive Name
ty f (b -> b) -> f b -> f b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> f b
rest

deriveFunctor :: Name -> Q [Dec]
deriveFunctor :: Name -> Q [Dec]
deriveFunctor Name
ty = do
   TypeQ
t <- Name -> TypeQ
varT (Name -> TypeQ) -> Q Name -> Q TypeQ
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Q Name
newName String
"t"
   (TypeQ
instanceType, [Con]
cs) <- Name -> Q (TypeQ, [Con])
reifyConstructors Name
ty
   let shallowConstraint :: TypeQ -> TypeQ
shallowConstraint TypeQ
ty = Name -> TypeQ
conT ''Transformation.Shallow.Functor TypeQ -> TypeQ -> TypeQ
`appT` TypeQ
t TypeQ -> TypeQ -> TypeQ
`appT` TypeQ
ty
       baseConstraint :: TypeQ -> TypeQ
baseConstraint TypeQ
ty = Name -> TypeQ
conT ''Transformation.At TypeQ -> TypeQ -> TypeQ
`appT` TypeQ
t TypeQ -> TypeQ -> TypeQ
`appT` TypeQ
ty
   ([Type]
constraints, Dec
dec) <- (TypeQ -> TypeQ)
-> (TypeQ -> TypeQ) -> TypeQ -> [Con] -> Q ([Type], Dec)
genShallowmap TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType [Con]
cs
   [Q Dec] -> Q [Dec]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [CxtQ -> TypeQ -> [Q Dec] -> Q Dec
instanceD ([TypeQ] -> CxtQ
cxt ([TypeQ] -> CxtQ) -> [TypeQ] -> CxtQ
forall a b. (a -> b) -> a -> b
$ TypeQ -> TypeQ -> TypeQ
appT (Name -> TypeQ
conT ''Transformation.Transformation) TypeQ
t TypeQ -> [TypeQ] -> [TypeQ]
forall a. a -> [a] -> [a]
: (Type -> TypeQ) -> [Type] -> [TypeQ]
forall a b. (a -> b) -> [a] -> [b]
map Type -> TypeQ
forall (f :: * -> *) a. Applicative f => a -> f a
pure [Type]
constraints)
                       (TypeQ -> TypeQ
shallowConstraint TypeQ
instanceType)
                       [Dec -> Q Dec
forall (f :: * -> *) a. Applicative f => a -> f a
pure Dec
dec]]

deriveFoldable :: Name -> Q [Dec]
deriveFoldable :: Name -> Q [Dec]
deriveFoldable Name
ty = do
   TypeQ
t <- Name -> TypeQ
varT (Name -> TypeQ) -> Q Name -> Q TypeQ
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Q Name
newName String
"t"
   TypeQ
m <- Name -> TypeQ
varT (Name -> TypeQ) -> Q Name -> Q TypeQ
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Q Name
newName String
"m"
   (TypeQ
instanceType, [Con]
cs) <- Name -> Q (TypeQ, [Con])
reifyConstructors Name
ty
   let shallowConstraint :: TypeQ -> TypeQ
shallowConstraint TypeQ
ty = Name -> TypeQ
conT ''Transformation.Shallow.Foldable TypeQ -> TypeQ -> TypeQ
`appT` TypeQ
t TypeQ -> TypeQ -> TypeQ
`appT` TypeQ
ty
       baseConstraint :: TypeQ -> TypeQ
baseConstraint TypeQ
ty = Name -> TypeQ
conT ''Transformation.At TypeQ -> TypeQ -> TypeQ
`appT` TypeQ
t TypeQ -> TypeQ -> TypeQ
`appT` TypeQ
ty
   ([Type]
constraints, Dec
dec) <- (TypeQ -> TypeQ)
-> (TypeQ -> TypeQ) -> TypeQ -> [Con] -> Q ([Type], Dec)
genFoldMap TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType [Con]
cs
   [Q Dec] -> Q [Dec]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [CxtQ -> TypeQ -> [Q Dec] -> Q Dec
instanceD ([TypeQ] -> CxtQ
cxt (TypeQ -> TypeQ -> TypeQ
appT (Name -> TypeQ
conT ''Transformation.Transformation) TypeQ
t TypeQ -> [TypeQ] -> [TypeQ]
forall a. a -> [a] -> [a]
:
                             TypeQ -> TypeQ -> TypeQ
appT (TypeQ -> TypeQ -> TypeQ
appT TypeQ
equalityT (Name -> TypeQ
conT ''Transformation.Codomain TypeQ -> TypeQ -> TypeQ
`appT` TypeQ
t))
                                  (Name -> TypeQ
conT ''Const TypeQ -> TypeQ -> TypeQ
`appT` TypeQ
m) TypeQ -> [TypeQ] -> [TypeQ]
forall a. a -> [a] -> [a]
:
                             TypeQ -> TypeQ -> TypeQ
appT (Name -> TypeQ
conT ''Monoid) TypeQ
m TypeQ -> [TypeQ] -> [TypeQ]
forall a. a -> [a] -> [a]
: (Type -> TypeQ) -> [Type] -> [TypeQ]
forall a b. (a -> b) -> [a] -> [b]
map Type -> TypeQ
forall (f :: * -> *) a. Applicative f => a -> f a
pure [Type]
constraints))
                       (TypeQ -> TypeQ
shallowConstraint TypeQ
instanceType)
                       [Dec -> Q Dec
forall (f :: * -> *) a. Applicative f => a -> f a
pure Dec
dec]]

deriveTraversable :: Name -> Q [Dec]
deriveTraversable :: Name -> Q [Dec]
deriveTraversable Name
ty = do
   TypeQ
t <- Name -> TypeQ
varT (Name -> TypeQ) -> Q Name -> Q TypeQ
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Q Name
newName String
"t"
   TypeQ
m <- Name -> TypeQ
varT (Name -> TypeQ) -> Q Name -> Q TypeQ
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Q Name
newName String
"m"
   TypeQ
f <- Name -> TypeQ
varT (Name -> TypeQ) -> Q Name -> Q TypeQ
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Q Name
newName String
"f"
   (TypeQ
instanceType, [Con]
cs) <- Name -> Q (TypeQ, [Con])
reifyConstructors Name
ty
   let shallowConstraint :: TypeQ -> TypeQ
shallowConstraint TypeQ
ty = Name -> TypeQ
conT ''Transformation.Shallow.Traversable TypeQ -> TypeQ -> TypeQ
`appT` TypeQ
t TypeQ -> TypeQ -> TypeQ
`appT` TypeQ
ty
       baseConstraint :: TypeQ -> TypeQ
baseConstraint TypeQ
ty = Name -> TypeQ
conT ''Transformation.At TypeQ -> TypeQ -> TypeQ
`appT` TypeQ
t TypeQ -> TypeQ -> TypeQ
`appT` TypeQ
ty
   ([Type]
constraints, Dec
dec) <- (TypeQ -> TypeQ)
-> (TypeQ -> TypeQ) -> TypeQ -> [Con] -> Q ([Type], Dec)
genTraverse TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType [Con]
cs
   [Q Dec] -> Q [Dec]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [CxtQ -> TypeQ -> [Q Dec] -> Q Dec
instanceD ([TypeQ] -> CxtQ
cxt (TypeQ -> TypeQ -> TypeQ
appT (Name -> TypeQ
conT ''Transformation.Transformation) TypeQ
t TypeQ -> [TypeQ] -> [TypeQ]
forall a. a -> [a] -> [a]
:
                             TypeQ -> TypeQ -> TypeQ
appT (TypeQ -> TypeQ -> TypeQ
appT TypeQ
equalityT (Name -> TypeQ
conT ''Transformation.Codomain TypeQ -> TypeQ -> TypeQ
`appT` TypeQ
t))
                                  (Name -> TypeQ
conT ''Compose TypeQ -> TypeQ -> TypeQ
`appT` TypeQ
m TypeQ -> TypeQ -> TypeQ
`appT` TypeQ
f) TypeQ -> [TypeQ] -> [TypeQ]
forall a. a -> [a] -> [a]
:
                             TypeQ -> TypeQ -> TypeQ
appT (Name -> TypeQ
conT ''Applicative) TypeQ
m TypeQ -> [TypeQ] -> [TypeQ]
forall a. a -> [a] -> [a]
: (Type -> TypeQ) -> [Type] -> [TypeQ]
forall a b. (a -> b) -> [a] -> [b]
map Type -> TypeQ
forall (f :: * -> *) a. Applicative f => a -> f a
pure [Type]
constraints))
                       (TypeQ -> TypeQ
shallowConstraint TypeQ
instanceType)
                       [Dec -> Q Dec
forall (f :: * -> *) a. Applicative f => a -> f a
pure Dec
dec]]

substitute :: Type -> Q Type -> Q Type -> Q Type
substitute :: Type -> TypeQ -> TypeQ -> TypeQ
substitute Type
resultType = (Type -> Type -> Type) -> TypeQ -> TypeQ -> TypeQ
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 Type -> Type -> Type
substitute'
   where substitute' :: Type -> Type -> Type
substitute' Type
instanceType Type
argumentType =
            [(Name, Name)] -> Type -> Type
substituteVars (Type -> Type -> [(Name, Name)]
substitutions Type
resultType Type
instanceType) Type
argumentType
         substitutions :: Type -> Type -> [(Name, Name)]
substitutions (AppT Type
t1 (VarT Name
name1)) (AppT Type
t2 (VarT Name
name2)) = (Name
name1, Name
name2) (Name, Name) -> [(Name, Name)] -> [(Name, Name)]
forall a. a -> [a] -> [a]
: Type -> Type -> [(Name, Name)]
substitutions Type
t1 Type
t2
         substitutions Type
_t1 Type
_t2 = []
         substituteVars :: [(Name, Name)] -> Type -> Type
substituteVars [(Name, Name)]
subs (VarT Name
name) = Name -> Type
VarT (Name -> Maybe Name -> Name
forall a. a -> Maybe a -> a
fromMaybe Name
name (Maybe Name -> Name) -> Maybe Name -> Name
forall a b. (a -> b) -> a -> b
$ Name -> [(Name, Name)] -> Maybe Name
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Name
name [(Name, Name)]
subs)
         substituteVars [(Name, Name)]
subs (AppT Type
t1 Type
t2) = Type -> Type -> Type
AppT ([(Name, Name)] -> Type -> Type
substituteVars [(Name, Name)]
subs Type
t1) ([(Name, Name)] -> Type -> Type
substituteVars [(Name, Name)]
subs Type
t2)
         substituteVars [(Name, Name)]
_ Type
t = Type
t

reifyConstructors :: Name -> Q (TypeQ, [Con])
reifyConstructors :: Name -> Q (TypeQ, [Con])
reifyConstructors Name
ty = do
   (TyConI Dec
tyCon) <- Name -> Q Info
reify Name
ty
   (Name
tyConName, [TyVarBndr]
tyVars, Maybe Type
_kind, [Con]
cs) <- case Dec
tyCon of
      DataD [Type]
_ Name
nm [TyVarBndr]
tyVars Maybe Type
kind [Con]
cs [DerivClause]
_   -> (Name, [TyVarBndr], Maybe Type, [Con])
-> Q (Name, [TyVarBndr], Maybe Type, [Con])
forall (m :: * -> *) a. Monad m => a -> m a
return (Name
nm, [TyVarBndr]
tyVars, Maybe Type
kind, [Con]
cs)
      NewtypeD [Type]
_ Name
nm [TyVarBndr]
tyVars Maybe Type
kind Con
c [DerivClause]
_ -> (Name, [TyVarBndr], Maybe Type, [Con])
-> Q (Name, [TyVarBndr], Maybe Type, [Con])
forall (m :: * -> *) a. Monad m => a -> m a
return (Name
nm, [TyVarBndr]
tyVars, Maybe Type
kind, [Con
c])
      Dec
_ -> String -> Q (Name, [TyVarBndr], Maybe Type, [Con])
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"deriveApply: tyCon may not be a type synonym."

   let (KindedTV Name
tyVar  (AppT (AppT Type
ArrowT Type
StarT) Type
StarT) : [TyVarBndr]
_) = [TyVarBndr] -> [TyVarBndr]
forall a. [a] -> [a]
reverse [TyVarBndr]
tyVars
       instanceType :: TypeQ
instanceType           = (TypeQ -> TyVarBndr -> TypeQ) -> TypeQ -> [TyVarBndr] -> TypeQ
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl TypeQ -> TyVarBndr -> TypeQ
apply (Name -> TypeQ
conT Name
tyConName) ([TyVarBndr] -> [TyVarBndr]
forall a. [a] -> [a]
reverse ([TyVarBndr] -> [TyVarBndr]) -> [TyVarBndr] -> [TyVarBndr]
forall a b. (a -> b) -> a -> b
$ Int -> [TyVarBndr] -> [TyVarBndr]
forall a. Int -> [a] -> [a]
drop Int
1 ([TyVarBndr] -> [TyVarBndr]) -> [TyVarBndr] -> [TyVarBndr]
forall a b. (a -> b) -> a -> b
$ [TyVarBndr] -> [TyVarBndr]
forall a. [a] -> [a]
reverse [TyVarBndr]
tyVars)
       apply :: TypeQ -> TyVarBndr -> TypeQ
apply TypeQ
t (PlainTV Name
name)    = TypeQ -> TypeQ -> TypeQ
appT TypeQ
t (Name -> TypeQ
varT Name
name)
       apply TypeQ
t (KindedTV Name
name Type
_) = TypeQ -> TypeQ -> TypeQ
appT TypeQ
t (Name -> TypeQ
varT Name
name)

   Deriving -> Q ()
forall a. Typeable a => a -> Q ()
putQ (Name -> Name -> Deriving
Deriving Name
tyConName Name
tyVar)
   (TypeQ, [Con]) -> Q (TypeQ, [Con])
forall (m :: * -> *) a. Monad m => a -> m a
return (TypeQ
instanceType, [Con]
cs)

genShallowmap :: (Q Type -> Q Type) -> (Q Type -> Q Type) -> Q Type -> [Con] -> Q ([Type], Dec)
genShallowmap :: (TypeQ -> TypeQ)
-> (TypeQ -> TypeQ) -> TypeQ -> [Con] -> Q ([Type], Dec)
genShallowmap TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType [Con]
cs = do
   ([[Type]]
constraints, [Clause]
clauses) <- [([Type], Clause)] -> ([[Type]], [Clause])
forall a b. [(a, b)] -> ([a], [b])
unzip ([([Type], Clause)] -> ([[Type]], [Clause]))
-> Q [([Type], Clause)] -> Q ([[Type]], [Clause])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Con -> Q ([Type], Clause)) -> [Con] -> Q [([Type], Clause)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ((TypeQ -> TypeQ)
-> (TypeQ -> TypeQ) -> TypeQ -> Con -> Q ([Type], Clause)
genShallowmapClause TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType) [Con]
cs
   ([Type], Dec) -> Q ([Type], Dec)
forall (m :: * -> *) a. Monad m => a -> m a
return ([[Type]] -> [Type]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Type]]
constraints, Name -> [Clause] -> Dec
FunD '(Transformation.Shallow.<$>) [Clause]
clauses)

genFoldMap :: (Q Type -> Q Type) -> (Q Type -> Q Type) -> Q Type -> [Con] -> Q ([Type], Dec)
genFoldMap :: (TypeQ -> TypeQ)
-> (TypeQ -> TypeQ) -> TypeQ -> [Con] -> Q ([Type], Dec)
genFoldMap TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType [Con]
cs = do
   ([[Type]]
constraints, [Clause]
clauses) <- [([Type], Clause)] -> ([[Type]], [Clause])
forall a b. [(a, b)] -> ([a], [b])
unzip ([([Type], Clause)] -> ([[Type]], [Clause]))
-> Q [([Type], Clause)] -> Q ([[Type]], [Clause])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Con -> Q ([Type], Clause)) -> [Con] -> Q [([Type], Clause)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ((TypeQ -> TypeQ)
-> (TypeQ -> TypeQ) -> TypeQ -> Con -> Q ([Type], Clause)
genFoldMapClause TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType) [Con]
cs
   ([Type], Dec) -> Q ([Type], Dec)
forall (m :: * -> *) a. Monad m => a -> m a
return ([[Type]] -> [Type]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Type]]
constraints, Name -> [Clause] -> Dec
FunD 'Transformation.Shallow.foldMap [Clause]
clauses)

genTraverse :: (Q Type -> Q Type) -> (Q Type -> Q Type) -> Q Type -> [Con] -> Q ([Type], Dec)
genTraverse :: (TypeQ -> TypeQ)
-> (TypeQ -> TypeQ) -> TypeQ -> [Con] -> Q ([Type], Dec)
genTraverse TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType [Con]
cs = do
   ([[Type]]
constraints, [Clause]
clauses) <- [([Type], Clause)] -> ([[Type]], [Clause])
forall a b. [(a, b)] -> ([a], [b])
unzip
     ([([Type], Clause)] -> ([[Type]], [Clause]))
-> Q [([Type], Clause)] -> Q ([[Type]], [Clause])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Con -> Q ([Type], Clause)) -> [Con] -> Q [([Type], Clause)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (GenTraverseFieldType
-> (TypeQ -> TypeQ)
-> (TypeQ -> TypeQ)
-> TypeQ
-> Con
-> Q ([Type], Clause)
genTraverseClause GenTraverseFieldType
genTraverseField TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType) [Con]
cs
   ([Type], Dec) -> Q ([Type], Dec)
forall (m :: * -> *) a. Monad m => a -> m a
return ([[Type]] -> [Type]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Type]]
constraints, Name -> [Clause] -> Dec
FunD 'Transformation.Shallow.traverse [Clause]
clauses)

genShallowmapClause :: (Q Type -> Q Type) -> (Q Type -> Q Type) -> Q Type -> Con -> Q ([Type], Clause)
genShallowmapClause :: (TypeQ -> TypeQ)
-> (TypeQ -> TypeQ) -> TypeQ -> Con -> Q ([Type], Clause)
genShallowmapClause TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType (NormalC Name
name [BangType]
fieldTypes) = do
   Name
t          <- String -> Q Name
newName String
"t"
   [Name]
fieldNames <- Int -> Q Name -> Q [Name]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM ([BangType] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [BangType]
fieldTypes) (String -> Q Name
newName String
"x")
   let pats :: [PatQ]
pats = [Name -> PatQ
varP Name
t, PatQ -> PatQ
parensP (Name -> [PatQ] -> PatQ
conP Name
name ([PatQ] -> PatQ) -> [PatQ] -> PatQ
forall a b. (a -> b) -> a -> b
$ (Name -> PatQ) -> [Name] -> [PatQ]
forall a b. (a -> b) -> [a] -> [b]
map Name -> PatQ
varP [Name]
fieldNames)]
       constraintsAndFields :: [Q ([Type], Exp)]
constraintsAndFields = (Name -> BangType -> Q ([Type], Exp))
-> [Name] -> [BangType] -> [Q ([Type], Exp)]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Name -> BangType -> Q ([Type], Exp)
newField [Name]
fieldNames [BangType]
fieldTypes
       newFields :: [Q Exp]
newFields = (Q ([Type], Exp) -> Q Exp) -> [Q ([Type], Exp)] -> [Q Exp]
forall a b. (a -> b) -> [a] -> [b]
map (([Type], Exp) -> Exp
forall a b. (a, b) -> b
snd (([Type], Exp) -> Exp) -> Q ([Type], Exp) -> Q Exp
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>) [Q ([Type], Exp)]
constraintsAndFields
       body :: BodyQ
body = Q Exp -> BodyQ
normalB (Q Exp -> BodyQ) -> Q Exp -> BodyQ
forall a b. (a -> b) -> a -> b
$ [Q Exp] -> Q Exp
appsE ([Q Exp] -> Q Exp) -> [Q Exp] -> Q Exp
forall a b. (a -> b) -> a -> b
$ Name -> Q Exp
conE Name
name Q Exp -> [Q Exp] -> [Q Exp]
forall a. a -> [a] -> [a]
: [Q Exp]
newFields
       newField :: Name -> BangType -> Q ([Type], Exp)
       newField :: Name -> BangType -> Q ([Type], Exp)
newField Name
x (Bang
_, Type
fieldType) = GenTraverseFieldType
genShallowmapField (Name -> Q Exp
varE Name
t) Type
fieldType TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint (Name -> Q Exp
varE Name
x) Q Exp -> Q Exp
forall a. a -> a
id
   [Type]
constraints <- ([[Type]] -> [Type]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Type]] -> [Type])
-> ([([Type], Exp)] -> [[Type]]) -> [([Type], Exp)] -> [Type]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([Type], Exp) -> [Type]
forall a b. (a, b) -> a
fst (([Type], Exp) -> [Type]) -> [([Type], Exp)] -> [[Type]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>)) ([([Type], Exp)] -> [Type]) -> Q [([Type], Exp)] -> CxtQ
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Q ([Type], Exp)] -> Q [([Type], Exp)]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [Q ([Type], Exp)]
constraintsAndFields
   (,) [Type]
constraints (Clause -> ([Type], Clause)) -> Q Clause -> Q ([Type], Clause)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [PatQ] -> BodyQ -> [Q Dec] -> Q Clause
clause [PatQ]
pats BodyQ
body []
genShallowmapClause TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType (RecC Name
name [VarBangType]
fields) = do
   Name
t <- String -> Q Name
newName String
"t"
   Name
x <- String -> Q Name
newName String
"x"
   let body :: BodyQ
body = Q Exp -> BodyQ
normalB (Q Exp -> BodyQ) -> Q Exp -> BodyQ
forall a b. (a -> b) -> a -> b
$ Name -> [Q (Name, Exp)] -> Q Exp
recConE Name
name ([Q (Name, Exp)] -> Q Exp) -> [Q (Name, Exp)] -> Q Exp
forall a b. (a -> b) -> a -> b
$ (([Type], (Name, Exp)) -> (Name, Exp)
forall a b. (a, b) -> b
snd (([Type], (Name, Exp)) -> (Name, Exp))
-> Q ([Type], (Name, Exp)) -> Q (Name, Exp)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>) (Q ([Type], (Name, Exp)) -> Q (Name, Exp))
-> [Q ([Type], (Name, Exp))] -> [Q (Name, Exp)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Q ([Type], (Name, Exp))]
constraintsAndFields
       constraintsAndFields :: [Q ([Type], (Name, Exp))]
constraintsAndFields = (VarBangType -> Q ([Type], (Name, Exp)))
-> [VarBangType] -> [Q ([Type], (Name, Exp))]
forall a b. (a -> b) -> [a] -> [b]
map VarBangType -> Q ([Type], (Name, Exp))
newNamedField [VarBangType]
fields
       newNamedField :: VarBangType -> Q ([Type], (Name, Exp))
       newNamedField :: VarBangType -> Q ([Type], (Name, Exp))
newNamedField (Name
fieldName, Bang
_, Type
fieldType) =
          ((,) Name
fieldName (Exp -> (Name, Exp)) -> ([Type], Exp) -> ([Type], (Name, Exp))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>)
          (([Type], Exp) -> ([Type], (Name, Exp)))
-> Q ([Type], Exp) -> Q ([Type], (Name, Exp))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenTraverseFieldType
genShallowmapField (Name -> Q Exp
varE Name
t) Type
fieldType TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint (Q Exp -> Q Exp -> Q Exp
appE (Name -> Q Exp
varE Name
fieldName) (Name -> Q Exp
varE Name
x)) Q Exp -> Q Exp
forall a. a -> a
id
   [Type]
constraints <- ([[Type]] -> [Type]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Type]] -> [Type])
-> ([([Type], (Name, Exp))] -> [[Type]])
-> [([Type], (Name, Exp))]
-> [Type]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([Type], (Name, Exp)) -> [Type]
forall a b. (a, b) -> a
fst (([Type], (Name, Exp)) -> [Type])
-> [([Type], (Name, Exp))] -> [[Type]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>)) ([([Type], (Name, Exp))] -> [Type])
-> Q [([Type], (Name, Exp))] -> CxtQ
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Q ([Type], (Name, Exp))] -> Q [([Type], (Name, Exp))]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [Q ([Type], (Name, Exp))]
constraintsAndFields
   (,) [Type]
constraints (Clause -> ([Type], Clause)) -> Q Clause -> Q ([Type], Clause)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [PatQ] -> BodyQ -> [Q Dec] -> Q Clause
clause [Name -> PatQ
varP Name
t, Name
x Name -> PatQ -> PatQ
`asP` Name -> [FieldPatQ] -> PatQ
recP Name
name []] BodyQ
body []
genShallowmapClause TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType
                    (GadtC [Name
name] [BangType]
fieldTypes (AppT Type
resultType (VarT Name
tyVar))) =
   do Just (Deriving Name
tyConName Name
_tyVar) <- Q (Maybe Deriving)
forall a. Typeable a => Q (Maybe a)
getQ
      Deriving -> Q ()
forall a. Typeable a => a -> Q ()
putQ (Name -> Name -> Deriving
Deriving Name
tyConName Name
tyVar)
      (TypeQ -> TypeQ)
-> (TypeQ -> TypeQ) -> TypeQ -> Con -> Q ([Type], Clause)
genShallowmapClause (TypeQ -> TypeQ
shallowConstraint (TypeQ -> TypeQ) -> (TypeQ -> TypeQ) -> TypeQ -> TypeQ
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type -> TypeQ -> TypeQ -> TypeQ
substitute Type
resultType TypeQ
instanceType)
                       (TypeQ -> TypeQ
baseConstraint (TypeQ -> TypeQ) -> (TypeQ -> TypeQ) -> TypeQ -> TypeQ
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type -> TypeQ -> TypeQ -> TypeQ
substitute Type
resultType TypeQ
instanceType)
                       TypeQ
instanceType (Name -> [BangType] -> Con
NormalC Name
name [BangType]
fieldTypes)
genShallowmapClause TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType
                    (RecGadtC [Name
name] [VarBangType]
fields (AppT Type
resultType (VarT Name
tyVar))) =
   do Just (Deriving Name
tyConName Name
_tyVar) <- Q (Maybe Deriving)
forall a. Typeable a => Q (Maybe a)
getQ
      Deriving -> Q ()
forall a. Typeable a => a -> Q ()
putQ (Name -> Name -> Deriving
Deriving Name
tyConName Name
tyVar)
      (TypeQ -> TypeQ)
-> (TypeQ -> TypeQ) -> TypeQ -> Con -> Q ([Type], Clause)
genShallowmapClause (TypeQ -> TypeQ
shallowConstraint (TypeQ -> TypeQ) -> (TypeQ -> TypeQ) -> TypeQ -> TypeQ
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type -> TypeQ -> TypeQ -> TypeQ
substitute Type
resultType TypeQ
instanceType)
                       (TypeQ -> TypeQ
baseConstraint (TypeQ -> TypeQ) -> (TypeQ -> TypeQ) -> TypeQ -> TypeQ
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type -> TypeQ -> TypeQ -> TypeQ
substitute Type
resultType TypeQ
instanceType)
                       TypeQ
instanceType (Name -> [VarBangType] -> Con
RecC Name
name [VarBangType]
fields)
genShallowmapClause TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType (ForallC [TyVarBndr]
_vars [Type]
_cxt Con
con) =
   (TypeQ -> TypeQ)
-> (TypeQ -> TypeQ) -> TypeQ -> Con -> Q ([Type], Clause)
genShallowmapClause TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType Con
con

genFoldMapClause :: (Q Type -> Q Type) -> (Q Type -> Q Type) -> Q Type -> Con -> Q ([Type], Clause)
genFoldMapClause :: (TypeQ -> TypeQ)
-> (TypeQ -> TypeQ) -> TypeQ -> Con -> Q ([Type], Clause)
genFoldMapClause TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType (NormalC Name
name [BangType]
fieldTypes) = do
   Name
t          <- String -> Q Name
newName String
"t"
   [Name]
fieldNames <- Int -> Q Name -> Q [Name]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM ([BangType] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [BangType]
fieldTypes) (String -> Q Name
newName String
"x")
   let pats :: [PatQ]
pats = [Name -> PatQ
varP Name
t, Name -> [PatQ] -> PatQ
conP Name
name ((Name -> PatQ) -> [Name] -> [PatQ]
forall a b. (a -> b) -> [a] -> [b]
map Name -> PatQ
varP [Name]
fieldNames)]
       constraintsAndFields :: [Q ([Type], Exp)]
constraintsAndFields = (Name -> BangType -> Q ([Type], Exp))
-> [Name] -> [BangType] -> [Q ([Type], Exp)]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Name -> BangType -> Q ([Type], Exp)
newField [Name]
fieldNames [BangType]
fieldTypes
       body :: Q Exp
body | [Name] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Name]
fieldNames = [| mempty |]
            | Bool
otherwise = (Q Exp -> Q Exp -> Q Exp) -> [Q Exp] -> Q Exp
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 Q Exp -> Q Exp -> Q Exp
append ([Q Exp] -> Q Exp) -> [Q Exp] -> Q Exp
forall a b. (a -> b) -> a -> b
$ (([Type], Exp) -> Exp
forall a b. (a, b) -> b
snd (([Type], Exp) -> Exp) -> Q ([Type], Exp) -> Q Exp
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>) (Q ([Type], Exp) -> Q Exp) -> [Q ([Type], Exp)] -> [Q Exp]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Q ([Type], Exp)]
constraintsAndFields
       append :: Q Exp -> Q Exp -> Q Exp
append Q Exp
a Q Exp
b = [| $(a) <> $(b) |]
       newField :: Name -> BangType -> Q ([Type], Exp)
       newField :: Name -> BangType -> Q ([Type], Exp)
newField Name
x (Bang
_, Type
fieldType) = GenTraverseFieldType
genFoldMapField (Name -> Q Exp
varE Name
t) Type
fieldType TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint (Name -> Q Exp
varE Name
x) Q Exp -> Q Exp
forall a. a -> a
id
   [Type]
constraints <- ([[Type]] -> [Type]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Type]] -> [Type])
-> ([([Type], Exp)] -> [[Type]]) -> [([Type], Exp)] -> [Type]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([Type], Exp) -> [Type]
forall a b. (a, b) -> a
fst (([Type], Exp) -> [Type]) -> [([Type], Exp)] -> [[Type]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>)) ([([Type], Exp)] -> [Type]) -> Q [([Type], Exp)] -> CxtQ
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Q ([Type], Exp)] -> Q [([Type], Exp)]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [Q ([Type], Exp)]
constraintsAndFields
   (,) [Type]
constraints (Clause -> ([Type], Clause)) -> Q Clause -> Q ([Type], Clause)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [PatQ] -> BodyQ -> [Q Dec] -> Q Clause
clause [PatQ]
pats (Q Exp -> BodyQ
normalB Q Exp
body) []
genFoldMapClause TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType (RecC Name
name [VarBangType]
fields) = do
   Name
t <- String -> Q Name
newName String
"t"
   Name
x <- String -> Q Name
newName String
"x"
   let body :: Q Exp
body | [VarBangType] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [VarBangType]
fields = [| mempty |]
            | Bool
otherwise = (Q Exp -> Q Exp -> Q Exp) -> [Q Exp] -> Q Exp
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 Q Exp -> Q Exp -> Q Exp
append ([Q Exp] -> Q Exp) -> [Q Exp] -> Q Exp
forall a b. (a -> b) -> a -> b
$ (([Type], Exp) -> Exp
forall a b. (a, b) -> b
snd (([Type], Exp) -> Exp) -> Q ([Type], Exp) -> Q Exp
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>) (Q ([Type], Exp) -> Q Exp) -> [Q ([Type], Exp)] -> [Q Exp]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Q ([Type], Exp)]
constraintsAndFields
       constraintsAndFields :: [Q ([Type], Exp)]
constraintsAndFields = (VarBangType -> Q ([Type], Exp))
-> [VarBangType] -> [Q ([Type], Exp)]
forall a b. (a -> b) -> [a] -> [b]
map VarBangType -> Q ([Type], Exp)
newField [VarBangType]
fields
       append :: Q Exp -> Q Exp -> Q Exp
append Q Exp
a Q Exp
b = [| $(a) <> $(b) |]
       newField :: VarBangType -> Q ([Type], Exp)
       newField :: VarBangType -> Q ([Type], Exp)
newField (Name
fieldName, Bang
_, Type
fieldType) =
          GenTraverseFieldType
genFoldMapField (Name -> Q Exp
varE Name
t) Type
fieldType TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint (Q Exp -> Q Exp -> Q Exp
appE (Name -> Q Exp
varE Name
fieldName) (Name -> Q Exp
varE Name
x)) Q Exp -> Q Exp
forall a. a -> a
id
   [Type]
constraints <- ([[Type]] -> [Type]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Type]] -> [Type])
-> ([([Type], Exp)] -> [[Type]]) -> [([Type], Exp)] -> [Type]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([Type], Exp) -> [Type]
forall a b. (a, b) -> a
fst (([Type], Exp) -> [Type]) -> [([Type], Exp)] -> [[Type]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>)) ([([Type], Exp)] -> [Type]) -> Q [([Type], Exp)] -> CxtQ
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Q ([Type], Exp)] -> Q [([Type], Exp)]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [Q ([Type], Exp)]
constraintsAndFields
   (,) [Type]
constraints (Clause -> ([Type], Clause)) -> Q Clause -> Q ([Type], Clause)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [PatQ] -> BodyQ -> [Q Dec] -> Q Clause
clause [Name -> PatQ
varP Name
t, Name
x Name -> PatQ -> PatQ
`asP` Name -> [FieldPatQ] -> PatQ
recP Name
name []] (Q Exp -> BodyQ
normalB Q Exp
body) []
genFoldMapClause TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType
                 (GadtC [Name
name] [BangType]
fieldTypes (AppT Type
resultType (VarT Name
tyVar))) =
   do Just (Deriving Name
tyConName Name
_tyVar) <- Q (Maybe Deriving)
forall a. Typeable a => Q (Maybe a)
getQ
      Deriving -> Q ()
forall a. Typeable a => a -> Q ()
putQ (Name -> Name -> Deriving
Deriving Name
tyConName Name
tyVar)
      (TypeQ -> TypeQ)
-> (TypeQ -> TypeQ) -> TypeQ -> Con -> Q ([Type], Clause)
genFoldMapClause (TypeQ -> TypeQ
shallowConstraint (TypeQ -> TypeQ) -> (TypeQ -> TypeQ) -> TypeQ -> TypeQ
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type -> TypeQ -> TypeQ -> TypeQ
substitute Type
resultType TypeQ
instanceType)
                       (TypeQ -> TypeQ
baseConstraint (TypeQ -> TypeQ) -> (TypeQ -> TypeQ) -> TypeQ -> TypeQ
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type -> TypeQ -> TypeQ -> TypeQ
substitute Type
resultType TypeQ
instanceType)
                       TypeQ
instanceType (Name -> [BangType] -> Con
NormalC Name
name [BangType]
fieldTypes)
genFoldMapClause TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType
                 (RecGadtC [Name
name] [VarBangType]
fields (AppT Type
resultType (VarT Name
tyVar))) =
   do Just (Deriving Name
tyConName Name
_tyVar) <- Q (Maybe Deriving)
forall a. Typeable a => Q (Maybe a)
getQ
      Deriving -> Q ()
forall a. Typeable a => a -> Q ()
putQ (Name -> Name -> Deriving
Deriving Name
tyConName Name
tyVar)
      (TypeQ -> TypeQ)
-> (TypeQ -> TypeQ) -> TypeQ -> Con -> Q ([Type], Clause)
genFoldMapClause (TypeQ -> TypeQ
shallowConstraint (TypeQ -> TypeQ) -> (TypeQ -> TypeQ) -> TypeQ -> TypeQ
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type -> TypeQ -> TypeQ -> TypeQ
substitute Type
resultType TypeQ
instanceType)
                       (TypeQ -> TypeQ
baseConstraint (TypeQ -> TypeQ) -> (TypeQ -> TypeQ) -> TypeQ -> TypeQ
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type -> TypeQ -> TypeQ -> TypeQ
substitute Type
resultType TypeQ
instanceType)
                       TypeQ
instanceType (Name -> [VarBangType] -> Con
RecC Name
name [VarBangType]
fields)
genFoldMapClause TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType (ForallC [TyVarBndr]
_vars [Type]
_cxt Con
con) =
   (TypeQ -> TypeQ)
-> (TypeQ -> TypeQ) -> TypeQ -> Con -> Q ([Type], Clause)
genFoldMapClause TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType Con
con

type GenTraverseFieldType = Q Exp -> Type -> (Q Type -> Q Type) -> (Q Type -> Q Type) -> Q Exp -> (Q Exp -> Q Exp)
                            -> Q ([Type], Exp)

genTraverseClause :: GenTraverseFieldType -> (Q Type -> Q Type) -> (Q Type -> Q Type) -> Q Type -> Con
                  -> Q ([Type], Clause)
genTraverseClause :: GenTraverseFieldType
-> (TypeQ -> TypeQ)
-> (TypeQ -> TypeQ)
-> TypeQ
-> Con
-> Q ([Type], Clause)
genTraverseClause GenTraverseFieldType
genTraverseField TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType (NormalC Name
name [BangType]
fieldTypes) = do
   Name
t          <- String -> Q Name
newName String
"t"
   [Name]
fieldNames <- Int -> Q Name -> Q [Name]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM ([BangType] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [BangType]
fieldTypes) (String -> Q Name
newName String
"x")
   let pats :: [PatQ]
pats = [Name -> PatQ
varP Name
t, PatQ -> PatQ
parensP (Name -> [PatQ] -> PatQ
conP Name
name ([PatQ] -> PatQ) -> [PatQ] -> PatQ
forall a b. (a -> b) -> a -> b
$ (Name -> PatQ) -> [Name] -> [PatQ]
forall a b. (a -> b) -> [a] -> [b]
map Name -> PatQ
varP [Name]
fieldNames)]
       constraintsAndFields :: [Q ([Type], Exp)]
constraintsAndFields = (Name -> BangType -> Q ([Type], Exp))
-> [Name] -> [BangType] -> [Q ([Type], Exp)]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Name -> BangType -> Q ([Type], Exp)
newField [Name]
fieldNames [BangType]
fieldTypes
       newFields :: [Q Exp]
newFields = (Q ([Type], Exp) -> Q Exp) -> [Q ([Type], Exp)] -> [Q Exp]
forall a b. (a -> b) -> [a] -> [b]
map (([Type], Exp) -> Exp
forall a b. (a, b) -> b
snd (([Type], Exp) -> Exp) -> Q ([Type], Exp) -> Q Exp
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>) [Q ([Type], Exp)]
constraintsAndFields
       body :: Q Exp
body | [BangType] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [BangType]
fieldTypes = [| pure $(conE name) |]
            | Bool
otherwise = (Q Exp, Bool) -> Q Exp
forall a b. (a, b) -> a
fst ((Q Exp, Bool) -> Q Exp) -> (Q Exp, Bool) -> Q Exp
forall a b. (a -> b) -> a -> b
$ ((Q Exp, Bool) -> Q Exp -> (Q Exp, Bool))
-> (Q Exp, Bool) -> [Q Exp] -> (Q Exp, Bool)
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (Q Exp, Bool) -> Q Exp -> (Q Exp, Bool)
apply (Name -> Q Exp
conE Name
name, Bool
False) [Q Exp]
newFields
       apply :: (Q Exp, Bool) -> Q Exp -> (Q Exp, Bool)
apply (Q Exp
a, Bool
False) Q Exp
b = ([| $(a) <$> $(b) |], Bool
True)
       apply (Q Exp
a, Bool
True) Q Exp
b = ([| $(a) <*> $(b) |], Bool
True)
       newField :: Name -> BangType -> Q ([Type], Exp)
       newField :: Name -> BangType -> Q ([Type], Exp)
newField Name
x (Bang
_, Type
fieldType) = GenTraverseFieldType
genTraverseField (Name -> Q Exp
varE Name
t) Type
fieldType TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint (Name -> Q Exp
varE Name
x) Q Exp -> Q Exp
forall a. a -> a
id
   [Type]
constraints <- ([[Type]] -> [Type]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Type]] -> [Type])
-> ([([Type], Exp)] -> [[Type]]) -> [([Type], Exp)] -> [Type]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([Type], Exp) -> [Type]
forall a b. (a, b) -> a
fst (([Type], Exp) -> [Type]) -> [([Type], Exp)] -> [[Type]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>)) ([([Type], Exp)] -> [Type]) -> Q [([Type], Exp)] -> CxtQ
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Q ([Type], Exp)] -> Q [([Type], Exp)]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [Q ([Type], Exp)]
constraintsAndFields
   (,) [Type]
constraints (Clause -> ([Type], Clause)) -> Q Clause -> Q ([Type], Clause)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [PatQ] -> BodyQ -> [Q Dec] -> Q Clause
clause [PatQ]
pats (Q Exp -> BodyQ
normalB Q Exp
body) []
genTraverseClause GenTraverseFieldType
genTraverseField TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType (RecC Name
name [VarBangType]
fields) = do
   Name
f <- String -> Q Name
newName String
"f"
   Name
x <- String -> Q Name
newName String
"x"
   let constraintsAndFields :: [Q ([Type], (Name, Exp))]
constraintsAndFields = (VarBangType -> Q ([Type], (Name, Exp)))
-> [VarBangType] -> [Q ([Type], (Name, Exp))]
forall a b. (a -> b) -> [a] -> [b]
map VarBangType -> Q ([Type], (Name, Exp))
newNamedField [VarBangType]
fields
       body :: Q Exp
body | [VarBangType] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [VarBangType]
fields = [| pure $(conE name) |]
            | Bool
otherwise = (Q Exp, Bool) -> Q Exp
forall a b. (a, b) -> a
fst (((Q Exp, Bool) -> Q Exp -> (Q Exp, Bool))
-> (Q Exp, Bool) -> [Q Exp] -> (Q Exp, Bool)
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (Q Exp, Bool) -> Q Exp -> (Q Exp, Bool)
apply (Name -> Q Exp
conE Name
name, Bool
False) ([Q Exp] -> (Q Exp, Bool)) -> [Q Exp] -> (Q Exp, Bool)
forall a b. (a -> b) -> a -> b
$ (Q ([Type], (Name, Exp)) -> Q Exp)
-> [Q ([Type], (Name, Exp))] -> [Q Exp]
forall a b. (a -> b) -> [a] -> [b]
map ((Name, Exp) -> Exp
forall a b. (a, b) -> b
snd ((Name, Exp) -> Exp)
-> (([Type], (Name, Exp)) -> (Name, Exp))
-> ([Type], (Name, Exp))
-> Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Type], (Name, Exp)) -> (Name, Exp)
forall a b. (a, b) -> b
snd (([Type], (Name, Exp)) -> Exp) -> Q ([Type], (Name, Exp)) -> Q Exp
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>) [Q ([Type], (Name, Exp))]
constraintsAndFields)
       apply :: (Q Exp, Bool) -> Q Exp -> (Q Exp, Bool)
apply (Q Exp
a, Bool
False) Q Exp
b = ([| $(a) <$> $(b) |], Bool
True)
       apply (Q Exp
a, Bool
True) Q Exp
b = ([| $(a) <*> $(b) |], Bool
True)
       newNamedField :: VarBangType -> Q ([Type], (Name, Exp))
       newNamedField :: VarBangType -> Q ([Type], (Name, Exp))
newNamedField (Name
fieldName, Bang
_, Type
fieldType) =
          ((,) Name
fieldName (Exp -> (Name, Exp)) -> ([Type], Exp) -> ([Type], (Name, Exp))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>)
          (([Type], Exp) -> ([Type], (Name, Exp)))
-> Q ([Type], Exp) -> Q ([Type], (Name, Exp))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenTraverseFieldType
genTraverseField (Name -> Q Exp
varE Name
f) Type
fieldType TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint (Q Exp -> Q Exp -> Q Exp
appE (Name -> Q Exp
varE Name
fieldName) (Name -> Q Exp
varE Name
x)) Q Exp -> Q Exp
forall a. a -> a
id
   [Type]
constraints <- ([[Type]] -> [Type]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Type]] -> [Type])
-> ([([Type], (Name, Exp))] -> [[Type]])
-> [([Type], (Name, Exp))]
-> [Type]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([Type], (Name, Exp)) -> [Type]
forall a b. (a, b) -> a
fst (([Type], (Name, Exp)) -> [Type])
-> [([Type], (Name, Exp))] -> [[Type]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>)) ([([Type], (Name, Exp))] -> [Type])
-> Q [([Type], (Name, Exp))] -> CxtQ
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Q ([Type], (Name, Exp))] -> Q [([Type], (Name, Exp))]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [Q ([Type], (Name, Exp))]
constraintsAndFields
   (,) [Type]
constraints (Clause -> ([Type], Clause)) -> Q Clause -> Q ([Type], Clause)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [PatQ] -> BodyQ -> [Q Dec] -> Q Clause
clause [Name -> PatQ
varP Name
f, Name
x Name -> PatQ -> PatQ
`asP` Name -> [FieldPatQ] -> PatQ
recP Name
name []] (Q Exp -> BodyQ
normalB Q Exp
body) []
genTraverseClause GenTraverseFieldType
genTraverseField TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType
                  (GadtC [Name
name] [BangType]
fieldTypes (AppT Type
resultType (VarT Name
tyVar))) =
   do Just (Deriving Name
tyConName Name
_tyVar) <- Q (Maybe Deriving)
forall a. Typeable a => Q (Maybe a)
getQ
      Deriving -> Q ()
forall a. Typeable a => a -> Q ()
putQ (Name -> Name -> Deriving
Deriving Name
tyConName Name
tyVar)
      GenTraverseFieldType
-> (TypeQ -> TypeQ)
-> (TypeQ -> TypeQ)
-> TypeQ
-> Con
-> Q ([Type], Clause)
genTraverseClause GenTraverseFieldType
genTraverseField
        (TypeQ -> TypeQ
shallowConstraint (TypeQ -> TypeQ) -> (TypeQ -> TypeQ) -> TypeQ -> TypeQ
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type -> TypeQ -> TypeQ -> TypeQ
substitute Type
resultType TypeQ
instanceType)
        (TypeQ -> TypeQ
baseConstraint (TypeQ -> TypeQ) -> (TypeQ -> TypeQ) -> TypeQ -> TypeQ
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type -> TypeQ -> TypeQ -> TypeQ
substitute Type
resultType TypeQ
instanceType)
        TypeQ
instanceType (Name -> [BangType] -> Con
NormalC Name
name [BangType]
fieldTypes)
genTraverseClause GenTraverseFieldType
genTraverseField TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType
                  (RecGadtC [Name
name] [VarBangType]
fields (AppT Type
resultType (VarT Name
tyVar))) =
   do Just (Deriving Name
tyConName Name
_tyVar) <- Q (Maybe Deriving)
forall a. Typeable a => Q (Maybe a)
getQ
      Deriving -> Q ()
forall a. Typeable a => a -> Q ()
putQ (Name -> Name -> Deriving
Deriving Name
tyConName Name
tyVar)
      GenTraverseFieldType
-> (TypeQ -> TypeQ)
-> (TypeQ -> TypeQ)
-> TypeQ
-> Con
-> Q ([Type], Clause)
genTraverseClause GenTraverseFieldType
genTraverseField
                        (TypeQ -> TypeQ
shallowConstraint (TypeQ -> TypeQ) -> (TypeQ -> TypeQ) -> TypeQ -> TypeQ
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type -> TypeQ -> TypeQ -> TypeQ
substitute Type
resultType TypeQ
instanceType)
                        (TypeQ -> TypeQ
baseConstraint (TypeQ -> TypeQ) -> (TypeQ -> TypeQ) -> TypeQ -> TypeQ
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type -> TypeQ -> TypeQ -> TypeQ
substitute Type
resultType TypeQ
instanceType)
                        TypeQ
instanceType (Name -> [VarBangType] -> Con
RecC Name
name [VarBangType]
fields)
genTraverseClause GenTraverseFieldType
genTraverseField TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType (ForallC [TyVarBndr]
_vars [Type]
_cxt Con
con) =
   GenTraverseFieldType
-> (TypeQ -> TypeQ)
-> (TypeQ -> TypeQ)
-> TypeQ
-> Con
-> Q ([Type], Clause)
genTraverseClause GenTraverseFieldType
genTraverseField TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint TypeQ
instanceType Con
con

genShallowmapField :: Q Exp -> Type -> (Q Type -> Q Type) -> (Q Type -> Q Type) -> Q Exp -> (Q Exp -> Q Exp)
                -> Q ([Type], Exp)
genShallowmapField :: GenTraverseFieldType
genShallowmapField Q Exp
trans Type
fieldType TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint Q Exp
fieldAccess Q Exp -> Q Exp
wrap = do
   Just (Deriving Name
_ Name
typeVar) <- Q (Maybe Deriving)
forall a. Typeable a => Q (Maybe a)
getQ
   case Type
fieldType of
     AppT Type
ty Type
a | Type
ty Type -> Type -> Bool
forall a. Eq a => a -> a -> Bool
== Name -> Type
VarT Name
typeVar ->
        (,) ([Type] -> Exp -> ([Type], Exp))
-> CxtQ -> Q (Exp -> ([Type], Exp))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((Type -> [Type] -> [Type]
forall a. a -> [a] -> [a]
:[]) (Type -> [Type]) -> TypeQ -> CxtQ
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TypeQ -> TypeQ
baseConstraint (Type -> TypeQ
forall (f :: * -> *) a. Applicative f => a -> f a
pure Type
a))
            Q (Exp -> ([Type], Exp)) -> Q Exp -> Q ([Type], Exp)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Q Exp -> Q Exp
wrap (Name -> Q Exp
varE '(Transformation.$) Q Exp -> Q Exp -> Q Exp
`appE` Q Exp
trans) Q Exp -> Q Exp -> Q Exp
`appE` Q Exp
fieldAccess)
     AppT Type
t1 Type
t2 | Type
t1 Type -> Type -> Bool
forall a. Eq a => a -> a -> Bool
/= Name -> Type
VarT Name
typeVar ->
        GenTraverseFieldType
genShallowmapField Q Exp
trans Type
t2 TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint Q Exp
fieldAccess (Q Exp -> Q Exp
wrap (Q Exp -> Q Exp) -> (Q Exp -> Q Exp) -> Q Exp -> Q Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Q Exp -> Q Exp -> Q Exp
appE (Name -> Q Exp
varE '(<$>)))
     SigT Type
ty Type
_kind -> GenTraverseFieldType
genShallowmapField Q Exp
trans Type
ty TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint Q Exp
fieldAccess Q Exp -> Q Exp
wrap
     ParensT Type
ty -> GenTraverseFieldType
genShallowmapField Q Exp
trans Type
ty TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint Q Exp
fieldAccess Q Exp -> Q Exp
wrap
     Type
_ -> (,) [] (Exp -> ([Type], Exp)) -> Q Exp -> Q ([Type], Exp)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Q Exp
fieldAccess

genFoldMapField :: Q Exp -> Type -> (Q Type -> Q Type) -> (Q Type -> Q Type) -> Q Exp -> (Q Exp -> Q Exp)
                -> Q ([Type], Exp)
genFoldMapField :: GenTraverseFieldType
genFoldMapField Q Exp
trans Type
fieldType TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint Q Exp
fieldAccess Q Exp -> Q Exp
wrap = do
   Just (Deriving Name
_ Name
typeVar) <- Q (Maybe Deriving)
forall a. Typeable a => Q (Maybe a)
getQ
   case Type
fieldType of
     AppT Type
ty Type
a | Type
ty Type -> Type -> Bool
forall a. Eq a => a -> a -> Bool
== Name -> Type
VarT Name
typeVar ->
        (,) ([Type] -> Exp -> ([Type], Exp))
-> CxtQ -> Q (Exp -> ([Type], Exp))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((Type -> [Type] -> [Type]
forall a. a -> [a] -> [a]
:[]) (Type -> [Type]) -> TypeQ -> CxtQ
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TypeQ -> TypeQ
baseConstraint (Type -> TypeQ
forall (f :: * -> *) a. Applicative f => a -> f a
pure Type
a))
            Q (Exp -> ([Type], Exp)) -> Q Exp -> Q ([Type], Exp)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Q Exp -> Q Exp
wrap (Name -> Q Exp
varE '(.) Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE 'getConst Q Exp -> Q Exp -> Q Exp
`appE` (Name -> Q Exp
varE '(Transformation.$) Q Exp -> Q Exp -> Q Exp
`appE` Q Exp
trans))
                 Q Exp -> Q Exp -> Q Exp
`appE` Q Exp
fieldAccess)
     AppT Type
t1 Type
t2 | Type
t1 Type -> Type -> Bool
forall a. Eq a => a -> a -> Bool
/= Name -> Type
VarT Name
typeVar ->
                  GenTraverseFieldType
genFoldMapField Q Exp
trans Type
t2 TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint Q Exp
fieldAccess (Q Exp -> Q Exp
wrap (Q Exp -> Q Exp) -> (Q Exp -> Q Exp) -> Q Exp -> Q Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Q Exp -> Q Exp -> Q Exp
appE (Name -> Q Exp
varE 'foldMap))
     SigT Type
ty Type
_kind -> GenTraverseFieldType
genFoldMapField Q Exp
trans Type
ty TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint Q Exp
fieldAccess Q Exp -> Q Exp
wrap
     ParensT Type
ty -> GenTraverseFieldType
genFoldMapField Q Exp
trans Type
ty TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint Q Exp
fieldAccess Q Exp -> Q Exp
wrap
     Type
_ -> (,) [] (Exp -> ([Type], Exp)) -> Q Exp -> Q ([Type], Exp)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [| mempty |]

genTraverseField :: GenTraverseFieldType
genTraverseField :: GenTraverseFieldType
genTraverseField Q Exp
trans Type
fieldType TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint Q Exp
fieldAccess Q Exp -> Q Exp
wrap = do
   Just (Deriving Name
_ Name
typeVar) <- Q (Maybe Deriving)
forall a. Typeable a => Q (Maybe a)
getQ
   case Type
fieldType of
     AppT Type
ty Type
a  | Type
ty Type -> Type -> Bool
forall a. Eq a => a -> a -> Bool
== Name -> Type
VarT Name
typeVar ->
        (,) ([Type] -> Exp -> ([Type], Exp))
-> CxtQ -> Q (Exp -> ([Type], Exp))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((Type -> [Type] -> [Type]
forall a. a -> [a] -> [a]
:[]) (Type -> [Type]) -> TypeQ -> CxtQ
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TypeQ -> TypeQ
baseConstraint (Type -> TypeQ
forall (f :: * -> *) a. Applicative f => a -> f a
pure Type
a))
            Q (Exp -> ([Type], Exp)) -> Q Exp -> Q ([Type], Exp)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Q Exp -> Q Exp
wrap (Name -> Q Exp
varE '(.) Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE 'getCompose Q Exp -> Q Exp -> Q Exp
`appE` (Name -> Q Exp
varE '(Transformation.$) Q Exp -> Q Exp -> Q Exp
`appE` Q Exp
trans))
                 Q Exp -> Q Exp -> Q Exp
`appE` Q Exp
fieldAccess)
     AppT Type
t1 Type
t2 | Type
t1 Type -> Type -> Bool
forall a. Eq a => a -> a -> Bool
/= Name -> Type
VarT Name
typeVar ->
        GenTraverseFieldType
genTraverseField Q Exp
trans Type
t2 TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint Q Exp
fieldAccess (Q Exp -> Q Exp
wrap (Q Exp -> Q Exp) -> (Q Exp -> Q Exp) -> Q Exp -> Q Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Q Exp -> Q Exp -> Q Exp
appE (Name -> Q Exp
varE 'traverse))
     SigT Type
ty Type
_kind -> GenTraverseFieldType
genTraverseField Q Exp
trans Type
ty TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint Q Exp
fieldAccess Q Exp -> Q Exp
wrap
     ParensT Type
ty -> GenTraverseFieldType
genTraverseField Q Exp
trans Type
ty TypeQ -> TypeQ
shallowConstraint TypeQ -> TypeQ
baseConstraint Q Exp
fieldAccess Q Exp -> Q Exp
wrap
     Type
_ -> (,) [] (Exp -> ([Type], Exp)) -> Q Exp -> Q ([Type], Exp)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [| pure $fieldAccess |]