th-desugar- Functions to desugar Template Haskell

Copyright(C) 2014 Richard Eisenberg
LicenseBSD-style (see LICENSE)
MaintainerRichard Eisenberg (
Safe HaskellNone




Desugars full Template Haskell syntax into a smaller core syntax for further processing. The desugared types and constructors are prefixed with a D.


Desugared data types

data DExp Source

Corresponds to TH's Exp type. Note that DLamE takes names, not patterns.

data DLetDec Source

Declarations as used in a let statement.

data DPat Source

Corresponds to TH's Pat type.

data DKind Source

Corresponds to TH's Kind type, which is a synonym for Type. DKind, though, only contains constructors that make sense for kinds.

type DCxt = [DPred] Source

Corresponds to TH's Cxt

data DPred Source

Corresponds to TH's Pred

data DTyVarBndr Source

Corresponds to TH's TyVarBndr. Note that PlainTV x and KindedTV x StarT are distinct, so we retain that distinction here.

data DMatch Source

Corresponds to TH's Match type.


DMatch DPat DExp 

data DClause Source

Corresponds to TH's Clause type.


DClause [DPat] DExp 

data NewOrData Source

Is it a newtype or a data type?



data DCon Source

Corresponds to TH's Con type.

data DConFields Source

A list of fields either for a standard data constructor or a record data constructor.

type DStrictType = (Strict, DType) Source

Corresponds to TH's StrictType type.

type DVarStrictType = (Name, Strict, DType) Source

Corresponds to TH's VarStrictType type.

data DRuleBndr Source

Corresponds to TH's RuleBndr type.

data DTySynEqn Source

Corresponds to TH's TySynEqn type (to store type family equations).


DTySynEqn [DType] DType 

data DInfo Source

Corresponds to TH's Info type.


DTyConI DDec (Maybe [DInstanceDec]) 
DVarI Name DType (Maybe Name) Fixity

The Maybe Name stores the name of the enclosing definition (datatype, for a data constructor; class, for a method), if any

DTyVarI Name DKind 
DPrimTyConI Name Int Bool

The Int is the arity; the Bool is whether this tycon is unlifted.

type DInstanceDec Source


 = DDec

Guaranteed to be an instance declaration

data Role :: *

Role annotations




Eq Role 
Data Role 
Ord Role 
Show Role 
Generic Role 
Ppr Role 
Lift Role 
Typeable * Role 
type Rep Role = D1 D1Role ((:+:) ((:+:) (C1 C1_0Role U1) (C1 C1_1Role U1)) ((:+:) (C1 C1_2Role U1) (C1 C1_3Role U1))) 

data AnnTarget :: *


Eq AnnTarget 
Data AnnTarget 
Ord AnnTarget 
Show AnnTarget 
Generic AnnTarget 
Lift AnnTarget 
Typeable * AnnTarget 
type Rep AnnTarget = D1 D1AnnTarget ((:+:) (C1 C1_0AnnTarget U1) ((:+:) (C1 C1_1AnnTarget (S1 NoSelector (Rec0 Name))) (C1 C1_2AnnTarget (S1 NoSelector (Rec0 Name))))) 

The Desugar class

class Desugar th ds | ds -> th where Source

This class relates a TH type with its th-desugar type and allows conversions back and forth. The functional dependency goes only one way because Type and Kind are type synonyms, but they desugar to different types.


desugar :: DsMonad q => th -> q ds Source

sweeten :: ds -> th Source

Main desugaring functions

dsExp :: DsMonad q => Exp -> q DExp Source

Desugar an expression

dsDecs :: DsMonad q => [Dec] -> q [DDec] Source

Desugar arbitrary Decs

dsType :: DsMonad q => Type -> q DType Source

Desugar a type

dsKind :: DsMonad q => Kind -> q DKind Source

Desugar a kind

dsInfo :: DsMonad q => Info -> q DInfo Source

Desugar Info

dsPatOverExp :: DsMonad q => Pat -> DExp -> q (DPat, DExp) Source

Desugar a pattern, along with processing a (desugared) expression that is the entire scope of the variables bound in the pattern.

dsPatsOverExp :: DsMonad q => [Pat] -> DExp -> q ([DPat], DExp) Source

Desugar multiple patterns. Like dsPatOverExp.

dsPatX :: DsMonad q => Pat -> q (DPat, [(Name, DExp)]) Source

Desugar a pattern, returning a list of (Name, DExp) pairs of extra variables that must be bound within the scope of the pattern

dsLetDecs :: DsMonad q => [Dec] -> q [DLetDec] Source

Desugar Decs that can appear in a let expression

dsTvb :: DsMonad q => TyVarBndr -> q DTyVarBndr Source

Desugar a TyVarBndr

dsCxt :: DsMonad q => Cxt -> q DCxt Source

Desugar a Cxt

dsCon :: DsMonad q => Con -> q DCon Source

Desugar a single Con.

dsForeign :: DsMonad q => Foreign -> q DForeign Source

Desugar a Foreign.

dsPragma :: DsMonad q => Pragma -> q DPragma Source

Desugar a Pragma.

dsRuleBndr :: DsMonad q => RuleBndr -> q DRuleBndr Source

Desugar a RuleBndr.

Secondary desugaring functions

type PatM q = WriterT [(Name, DExp)] q Source

Desugaring a pattern also returns the list of variables bound in as-patterns and the values they should be bound to. This variables must be brought into scope in the "body" of the pattern.

dsPred :: DsMonad q => Pred -> q DCxt Source

Desugar a Pred, flattening any internal tuples

dsPat :: DsMonad q => Pat -> PatM q DPat Source

Desugar a pattern.

dsDec :: DsMonad q => Dec -> q [DDec] Source

Desugar a single Dec, perhaps producing multiple DDecs

dsLetDec :: DsMonad q => Dec -> q [DLetDec] Source

Desugar a single Dec, perhaps producing multiple DLetDecs

dsMatches Source


:: DsMonad q 
=> Name

Name of the scrutinee, which must be a bare var

-> [Match]

Matches of the case statement

-> q [DMatch] 

Desugar a list of matches for a case statement

dsBody Source


:: DsMonad q 
=> Body

body to desugar

-> [Dec]

"where" declarations

-> DExp

what to do if the guards don't match

-> q DExp 

Desugar a Body

dsGuards Source


:: DsMonad q 
=> [(Guard, Exp)]

Guarded expressions

-> DExp

What to do if none of the guards match

-> q DExp 

Desugar guarded expressions

dsDoStmts :: DsMonad q => [Stmt] -> q DExp Source

Desugar the Stmts in a do expression

dsComp :: DsMonad q => [Stmt] -> q DExp Source

Desugar the Stmts in a list or monad comprehension

dsClauses Source


:: DsMonad q 
=> Name

Name of the function

-> [Clause]

Clauses to desugar

-> q [DClause] 

Desugar clauses to a function definition

Converting desugared AST back to TH AST

Expanding type synonyms

expand :: (DsMonad q, Data a) => a -> q a Source

Expand all type synonyms and type families in the desugared abstract syntax tree provided, where type family simplification is on a "best effort" basis. Normally, the first parameter should have a type like DExp or DLetDec.

expandType :: DsMonad q => DType -> q DType Source

Expands all type synonyms in a desugared type. Also expands open type family applications, as long as the arguments have no free variables. Attempts to expand closed type family applications, but aborts the moment it spots anything strange, like a nested type family application or type variable.


reifyWithWarning :: Quasi q => Name -> q Info Source

Reify a declaration, warning the user about splices if the reify fails. The warning says that reification can fail if you try to reify a type in the same splice as it is declared.

The following definitions allow you to register a list of Decs to be used in reification queries.

withLocalDeclarations :: DsMonad q => [Dec] -> DsM q a -> q a Source

Add a list of declarations to be considered when reifying local declarations.

dsReify :: DsMonad q => Name -> q (Maybe DInfo) Source

Like reify, but safer and desugared. Uses local declarations where available.

reifyWithLocals_maybe :: DsMonad q => Name -> q (Maybe Info) Source

Like reify from Template Haskell, but looks also in any not-yet-typechecked declarations. To establish this list of not-yet-typechecked declarations, use withLocalDeclarations. Returns Nothing if reification fails. Note that no inferred type information is available from local declarations; bottoms may be used if necessary.

reifyWithLocals :: DsMonad q => Name -> q Info Source

Like reifyWithLocals_maybe, but throws an exception upon failure, warning the user about separating splices.

class Quasi m => DsMonad m where Source

A DsMonad stores some list of declarations that should be considered in scope. DsM is the prototypical inhabitant of DsMonad.


localDeclarations :: m [Dec] Source

Produce a list of local declarations.


DsMonad IO 
DsMonad Q 
Quasi q => DsMonad (DsM q) 
DsMonad m => DsMonad (ReaderT r m) 
DsMonad m => DsMonad (StateT s m) 
(DsMonad m, Monoid w) => DsMonad (WriterT w m) 
(DsMonad m, Monoid w) => DsMonad (RWST r w s m) 

data DsM q a Source

A convenient implementation of the DsMonad class. Use by calling withLocalDeclarations.


MonadTrans DsM 
Monad q => Monad (DsM q) 
Functor q => Functor (DsM q) 
Applicative q => Applicative (DsM q) 
Quasi q => Quasi (DsM q) 
Quasi q => DsMonad (DsM q) 

Nested pattern flattening

scExp :: DsMonad q => DExp -> q DExp Source

Remove all nested pattern-matches within this expression. This also removes all DTildePas and DBangPas. After this is run, every pattern is guaranteed to be either a DConPa with bare variables as arguments, a DLitPa, or a DWildPa.

scLetDec :: DsMonad q => DLetDec -> q DLetDec Source

Like scExp, but for a DLetDec.

Utility functions

applyDExp :: DExp -> [DExp] -> DExp Source

Apply one DExp to a list of arguments

applyDType :: DType -> [DType] -> DType Source

Apply one DType to a list of arguments

dPatToDExp :: DPat -> DExp Source

Convert a DPat to a DExp. Fails on DWildP.

removeWilds :: DsMonad q => DPat -> q DPat Source

Remove all wildcards from a pattern, replacing any wildcard with a fresh variable

getDataD Source


:: Quasi q 
=> String

Print this out on failure

-> Name

Name of the datatype (data or newtype) of interest

-> q ([TyVarBndr], [Con]) 

Extract the TyVarBndrs and constructors given the Name of a type

dataConNameToDataName :: Quasi q => Name -> q Name Source

From the name of a data constructor, retrive the datatype definition it is a part of.

dataConNameToCon :: Quasi q => Name -> q Con Source

From the name of a data constructor, retrieve its definition as a Con

nameOccursIn :: Data a => Name -> a -> Bool Source

Check if a name occurs anywhere within a TH tree.

allNamesIn :: Data a => a -> [Name] Source

Extract all Names mentioned in a TH tree.

flattenDValD :: Quasi q => DLetDec -> q [DLetDec] Source

If the declaration passed in is a DValD, creates new, equivalent declarations such that the DPat in all DValDs is just a plain DVarPa. Other declarations are passed through unchanged. Note that the declarations that come out of this function are rather less efficient than those that come in: they have many more pattern matches.

getRecordSelectors Source


:: Quasi q 
=> DType

the type of the argument

-> DCon 
-> q [DLetDec] 

Produces DLetDecs representing the record selector functions from the provided DCon.

mkTypeName :: Quasi q => String -> q Name Source

Like TH's lookupTypeName, but if this name is not bound, then we assume it is declared in the current module.

mkDataName :: Quasi q => String -> q Name Source

Like TH's lookupDataName, but if this name is not bound, then we assume it is declared in the current module.

newUniqueName :: Quasi q => String -> q Name Source

Like newName, but even more unique (unique across different splices), and with unique nameBases. Precondition: the string is a valid Haskell alphanumeric identifier (could be upper- or lower-case).

mkTupleDExp :: [DExp] -> DExp Source

Make a tuple DExp from a list of DExps. Avoids using a 1-tuple.

mkTupleDPat :: [DPat] -> DPat Source

Make a tuple DPat from a list of DPats. Avoids using a 1-tuple.

maybeDLetE :: [DLetDec] -> DExp -> DExp Source

If decs is non-empty, delcare them in a let:

maybeDCaseE :: String -> DExp -> [DMatch] -> DExp Source

If matches is non-empty, make a case statement; otherwise make an error statement

substTy :: DsMonad q => Map Name DType -> DType -> q DType Source

Capture-avoiding substitution on types

tupleDegree_maybe :: String -> Maybe Int Source

Extract the degree of a tuple

tupleNameDegree_maybe :: Name -> Maybe Int Source

Extract the degree of a tuple name

unboxedTupleDegree_maybe :: String -> Maybe Int Source

Extract the degree of an unboxed tuple

unboxedTupleNameDegree_maybe :: Name -> Maybe Int Source

Extract the degree of a tuple name

Extracting bound names

extractBoundNamesStmt :: Stmt -> Set Name Source

Extract the names bound in a Stmt

extractBoundNamesDec :: Dec -> Set Name Source

Extract the names bound in a Dec that could appear in a let expression.

extractBoundNamesPat :: Pat -> Set Name Source

Extract the names bound in a Pat