th-desugar-1.5: 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



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 open type families in the desugared abstract syntax tree provided. 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.


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.


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.

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