-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | Template Your Boilerplate - a Template Haskell version of SYB
--
-- TYB is a generic-programming system that uses Template Haskell to
-- generate boiler-plate traversals at compile time. This results in
-- significantly improved performance. The paper documenting it is
-- available at: http://cs.pdx.edu/~adamsmic/projects/tyb/TYB.pdf
@package TYB
@version 0.2.3
-- | This is the code for "Template Your Boilerplate" under review at the
-- Haskell Symposium 2012.
--
-- A draft copy of that paper is available at
-- http://cs.pdx.edu/~adamsmic/projects/tyb/TYB.pdf and provides
-- more thorough documentation.
module Data.Generics.TH
-- | Case expression generation. This is the core function of the Template
-- Your Boilerplate library.
--
-- This function is similar to thcase', except that since most
-- users will note care about the distinction between types and primitive
-- types, this function smooths over the differences by treating
-- primitive types as types with nullary constructors.
thcase :: Quasi m => (m Exp -> [(Type, m Exp)] -> m Exp) -> m Type -> m Exp
-- | Primitive case expression generation. Most users will want to use
-- thcase instead.
thcase' :: Quasi m => (Either Name (Name, [(Type, Name)]) -> m Exp) -> m Type -> m Exp
-- | Scrap Your Boilerplate style case expression generation. The
-- thcase function is generally simpler to use instead of this and
-- is more powerful.
thfoldl :: Quasi m => (m Exp -> Type -> m Exp -> m Exp) -> (m Exp -> m Exp) -> m Type -> m Exp
-- | Generic single-layer transformation
thmapT :: Quasi m => (Type -> m Exp) -> (m Type -> m Exp)
-- | Generic single-layer monadic transformation.
thmapM :: Quasi m => (Type -> m Exp) -> (m Type -> m Exp)
-- | Generic single-layer query.
thmapQ :: Quasi m => (Type -> m Exp) -> (m Type -> m Exp)
-- | Generic single-layer query (left associative).
thmapQl :: Quasi m => (m Exp) -> (m Exp) -> (Type -> m Exp) -> (m Type -> m Exp)
-- | Generic single-layer query (right associative).
thmapQr :: Quasi m => m Exp -> m Exp -> (Type -> m Exp) -> (m Type -> m Exp)
-- | Memoizes a code generation function. Most users will want to use
-- memoizeExp instead as it provides a simplified interface, but
-- all the notes about this function also apply to memoizeExp.
--
-- We memoize a function returning an Exp by creating a Dec
-- with a body that is the Exp returned by that function. The
-- return value of the function is replaced with a VarE that
-- refers to the Dec. This allows functions like everywhere
-- to avoid infinite recursions when they traverse recursive types like
-- lists.
--
-- The memoization functions come in two flavors: memoizeDec and
-- memoizeExp. With memoizeDec it is the responsibility of
-- the caller to place the Dec in an appropriate place. The
-- memoizeExp function automatically handles the Dec by
-- wrapping them in a local LetE form.
--
-- Every memoized function is passed a memoized version of itself. This
-- is the function that should be used in recursive calls. Failing to do
-- so will prevent those calls from being memoized.
--
-- Mutually recursive functions are possible using memoizeDec2,
-- etc. and memoizeExp2, etc.
--
-- If the function being memoized needs to accept multiple arguments,
-- then they must be packed into a tuple and passed as a single argument.
--
-- Effects in the m monad are only performed the first time the
-- memoized function is called with a particular argument. Subsequent
-- times the monad is simply the result of a return. Thus while it
-- is tempting to store extra return values in the monad, this should be
-- avoided due to the high likelihood of unexpected behavior.
--
-- Implementation Notes:
--
--
-- - Note that m should not store a copy of the function,
-- otherwise a memory leak is introduced. It wouldn't even make sense to
-- do it anyway since the results refer to expressions that might not be
-- in scope.
-- - The memoized function stores a reference to the memoization table,
-- Thus if a reference to the memoized function gets tucked inside
-- m, then a memory leak can be introduced. We could eliminate
-- this leak by clearing and invalidating the table when
-- memoizeDec returns. To fully do this properly the table would
-- have to be invalidated in such a way that the memoized version of the
-- function would not continue to try populating the table if the user
-- called it after memoizeDec return.
-- - Conceptually we should use a State monad instead of an IORef but
-- we choose IORef since we can embed IO operations in a Quasi without
-- imposing extra restrictions on m.
-- - Other designs are possible. This design was choosen for its
-- simplicity of use. The choice of memoization interface is largely
-- orthogonal to the rest of this library.
-- - Type synonyms and kind annotations may lead to duplicate versions
-- of the code (e.g. versions for both String and
-- [Char]) Usually this isn't a problem, but if it is,
-- then the type synonyms should be expanded before each call to the
-- memoized function.
-- - GADTs and data/type families haven't been considered in this code.
-- It is unknown whether they work.
--
--
-- Note that polymorphically recursive types (e.g. data F a = N a | F
-- (F (Int, a))) have an infinite number of types in them and thus
-- despite memoization this function will not terminate on those types.
memoizeDec :: (Quasi m, Ord a) => ((a -> m Exp) -> a -> m Exp) -> a -> m ([Dec], Exp)
-- | Simultaneously memoizes two code generation functions. All of the
-- notes about memoizeDec also apply to this function. Most users
-- will want to use memoizeExp2 instead of this function as it
-- provides a simplified interface.
memoizeDec2 :: (Quasi m, Ord a, Ord b) => ((a -> m Exp) -> (b -> m Exp) -> a -> m Exp) -> ((a -> m Exp) -> (b -> m Exp) -> b -> m Exp) -> a -> m ([Dec], Exp)
-- | Memoizes a code generation function. Behaves identically to
-- memoizeDec except that it returns a LetE that binds the
-- Dec resulting from memoizeDec for the Exp
-- resulting from memoizeDec.
memoizeExp :: (Quasi m, Ord a) => ((a -> m Exp) -> a -> m Exp) -> a -> m Exp
-- | Simultaneously memoizes two code generation functions. Behaves
-- identically to memoizeDec2 except that it returns a LetE
-- that binds the Dec resulting from memoizeDec2 for the
-- Exp resulting from memoizeDec2.
memoizeExp2 :: (Quasi m, Ord a, Ord b) => ((a -> m Exp) -> (b -> m Exp) -> a -> m Exp) -> ((a -> m Exp) -> (b -> m Exp) -> b -> m Exp) -> a -> m Exp
-- | Generic recursive transformation (bottom-up)
everywhere :: Quasi m => (Type -> m Exp) -> (m Type -> m Exp)
-- | Generic recursive transformation (top-down)
everywhere' :: Quasi m => (Type -> m Exp) -> (m Type -> m Exp)
-- | Generic recursive transformation (bottom-up) with selective traversal.
-- Skips traversal when a given query returns True.
everywhereBut :: Quasi m => (Type -> m Bool) -> (Type -> m Exp) -> (m Type -> m Exp)
-- | Generic recursive monadic transformation (bottom-up)
everywhereM :: Quasi m => (Type -> m Exp) -> (m Type -> m Exp)
-- | Generic recursive monadic transformation (top-down)
everywhereM' :: Quasi m => (Type -> m Exp) -> (m Type -> m Exp)
-- | Generic recursive monadic transformation (top-down) with selective
-- traversal. Skips traversal when a given query returns True.
everywhereButM' :: Quasi m => (Type -> m Bool) -> (Type -> m Exp) -> (m Type -> m Exp)
-- | Generic recursive transformation (bottom-up) with selective traversal.
-- Recurs on only types that can contain a type with type specific
-- behavior.
everywhereFor :: Quasi m => Name -> (m Type -> m Exp)
-- | Generic recursive monadic transformation (bottom-up) with selective
-- traversal. Recurs on only types that can contain a type with type
-- specific behavior.
everywhereForM :: Quasi m => Name -> (m Type -> m Exp)
-- | Generic recursive transformation (bottom-up) with selective traversal.
somewhere :: Quasi m => ((Type -> m Exp) -> (Type -> m (Maybe Exp))) -> (m Type -> m Exp)
-- | Generic recursive monadic transformation (bottom-up) with selective
-- traversal.
somewhereM :: Quasi m => ((Type -> m Exp) -> (Type -> m (Maybe Exp))) -> (m Type -> m Exp)
-- | Generic recursive query (bottom-up).
everything :: Quasi m => m Exp -> (Type -> m Exp) -> (m Type -> m Exp)
-- | Generic recursive query with selective traversal
everythingBut :: Quasi m => (m Exp) -> (Type -> m (Exp, Bool)) -> (m Type -> m Exp)
-- | Generic recursive query with left-associative accumulation.
everythingAccL :: (Type -> Q Exp) -> (Q Type -> Q Exp)
-- | Generic recursive query with strict left-associative accumulation
everythingAccL' :: (Type -> Q Exp) -> (Q Type -> Q Exp)
-- | Generic recursive query with left-associative accumulation and
-- selective traversal
everythingButAccL :: (Type -> Q (Exp, Bool)) -> (Q Type -> Q Exp)
-- | Generic recursive query with strict left-associative accumulation and
-- selective traversal
everythingButAccL' :: (Type -> Q (Exp, Bool)) -> (Q Type -> Q Exp)
-- | Generic recursive query with right-associative accumulation
everythingAccR :: (Type -> Q Exp) -> (Q Type -> Q Exp)
-- | Generic recursive query with right-associative accumulation and
-- selective traversal
everythingButAccR :: (Type -> Q (Exp, Bool)) -> (Q Type -> Q Exp)
-- | Generic recursive traversal using right-associative accumulation
everythingForR :: Name -> (Q Type -> Q Exp)
-- | Generic recursive traversal using left-associative accumulation
everythingForL :: Name -> (Q Type -> Q Exp)
-- | Generic recursive traversal using strict left-associative accumulation
everythingForL' :: Name -> (Q Type -> Q Exp)
-- | Extends a generic operation with type specific behavior based on the
-- type of the given name.
extN :: Quasi m => (Type -> m Exp) -> Name -> (Type -> m Exp)
-- | Extends a generic operation with type specific behavior.
extE :: Quasi m => (Type -> m exp) -> (Type -> m Bool, m exp) -> (Type -> m exp)
-- | Extends a generic operation with type specific behavior.
extE' :: Quasi m => (Type -> m exp) -> (Type -> m Bool, Type -> m exp) -> (Type -> m exp)
-- | Makes a transformation from a named function.
mkT :: Quasi m => Name -> (Type -> m Exp)
-- | Makes a transformation from several named functions.
mkTs :: Quasi m => [Name] -> (Type -> m Exp)
-- | Makes a query from a named function.
mkQ :: Quasi m => m Exp -> Name -> (Type -> m Exp)
-- | Makes a query from several named functions.
mkQs :: Quasi m => m Exp -> [Name] -> (Type -> m Exp)
-- | Makes a monadic transformation from a named function.
mkM :: Quasi m => Name -> (Type -> m Exp)
-- | Makes a monadic transformation from several named functions.
mkMs :: Quasi m => [Name] -> (Type -> m Exp)
-- | Tests if two types are equal modulo type synonyms and kind
-- annotations. Naive equality would fail to equate String and
-- [Char].
eqType :: Quasi m => m Type -> Type -> m Bool
-- | Test if any of a list of types is equal to a particular type modulo
-- type synonyms and kind annotations. Useful when multiple types share
-- the same type-specific behavior.
eqTypes :: Quasi m => [m Type] -> Type -> m Bool
-- | inType t1 t2 = True iff t1 is (even recursively)
-- inside t2
inType :: Quasi m => m Type -> Type -> m Bool
-- | inTypes ts t2 = True iff any of ts is (even
-- recursively) inside t2
inTypes :: Quasi m => [m Type] -> Type -> m Bool
-- | Returns the constructors of a given type. Returns Nothing if
-- the type is primitive.
constructorsOf :: Quasi m => Type -> m (Maybe [(Name, [Type])])
-- | Returns the type of a variable, method or constructor name.
typeOfName :: Quasi m => Name -> m Type