-- 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.2 -- | 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 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