Copyright | (C) 2014 Richard Eisenberg |
---|---|
License | BSD-style (see LICENSE) |
Maintainer | Richard Eisenberg (rae@cs.brynmawr.edu) |
Stability | experimental |
Portability | non-portable |
Safe Haskell | None |
Language | Haskell2010 |
Desugars full Template Haskell syntax into a smaller core syntax for further processing. The desugared types and constructors are prefixed with a D.
- data DExp
- data DLetDec
- data DPat
- data DType
- type DKind = DType
- type DCxt = [DPred]
- data DPred
- data DTyVarBndr
- data DMatch = DMatch DPat DExp
- data DClause = DClause [DPat] DExp
- data DDec
- = DLetDec DLetDec
- | DDataD NewOrData DCxt Name [DTyVarBndr] [DCon] [DDerivClause]
- | DTySynD Name [DTyVarBndr] DType
- | DClassD DCxt Name [DTyVarBndr] [FunDep] [DDec]
- | DInstanceD (Maybe Overlap) DCxt DType [DDec]
- | DForeignD DForeign
- | DOpenTypeFamilyD DTypeFamilyHead
- | DClosedTypeFamilyD DTypeFamilyHead [DTySynEqn]
- | DDataFamilyD Name [DTyVarBndr]
- | DDataInstD NewOrData DCxt Name [DType] [DCon] [DDerivClause]
- | DTySynInstD Name DTySynEqn
- | DRoleAnnotD Name [Role]
- | DStandaloneDerivD (Maybe DerivStrategy) DCxt DType
- | DDefaultSigD Name DType
- | DPatSynD Name PatSynArgs DPatSynDir DPat
- | DPatSynSigD Name DPatSynType
- data DDerivClause = DDerivClause (Maybe DerivStrategy) DCxt
- data DerivStrategy :: *
- data DPatSynDir
- = DUnidir
- | DImplBidir
- | DExplBidir [DClause]
- type DPatSynType = DType
- data Overlap :: *
- data PatSynArgs :: *
- = PrefixPatSyn [Name]
- | InfixPatSyn Name Name
- | RecordPatSyn [Name]
- data NewOrData
- data DTypeFamilyHead = DTypeFamilyHead Name [DTyVarBndr] DFamilyResultSig (Maybe InjectivityAnn)
- data DFamilyResultSig
- data InjectivityAnn :: * = InjectivityAnn Name [Name]
- data DCon = DCon [DTyVarBndr] DCxt Name DConFields (Maybe DType)
- data DConFields
- type DDeclaredInfix = Bool
- type DBangType = (Bang, DType)
- type DVarBangType = (Name, Bang, DType)
- data Bang :: * = Bang SourceUnpackedness SourceStrictness
- data SourceUnpackedness :: *
- data SourceStrictness :: *
- data DForeign
- data DPragma
- data DRuleBndr
- data DTySynEqn = DTySynEqn [DType] DType
- data DInfo
- type DInstanceDec = DDec
- data Role :: *
- data AnnTarget :: *
- class Desugar th ds | ds -> th where
- dsExp :: DsMonad q => Exp -> q DExp
- dsDecs :: DsMonad q => [Dec] -> q [DDec]
- dsType :: DsMonad q => Type -> q DType
- dsInfo :: DsMonad q => Info -> q DInfo
- dsPatOverExp :: DsMonad q => Pat -> DExp -> q (DPat, DExp)
- dsPatsOverExp :: DsMonad q => [Pat] -> DExp -> q ([DPat], DExp)
- dsPatX :: DsMonad q => Pat -> q (DPat, [(Name, DExp)])
- dsLetDecs :: DsMonad q => [Dec] -> q [DLetDec]
- dsTvb :: DsMonad q => TyVarBndr -> q DTyVarBndr
- dsCxt :: DsMonad q => Cxt -> q DCxt
- dsCon :: DsMonad q => Con -> q [DCon]
- dsForeign :: DsMonad q => Foreign -> q DForeign
- dsPragma :: DsMonad q => Pragma -> q DPragma
- dsRuleBndr :: DsMonad q => RuleBndr -> q DRuleBndr
- type PatM q = WriterT [(Name, DExp)] q
- dsPred :: DsMonad q => Pred -> q DCxt
- dsPat :: DsMonad q => Pat -> PatM q DPat
- dsDec :: DsMonad q => Dec -> q [DDec]
- dsDerivClause :: DsMonad q => DerivClause -> q DDerivClause
- dsLetDec :: DsMonad q => Dec -> q [DLetDec]
- dsMatches :: DsMonad q => Name -> [Match] -> q [DMatch]
- dsBody :: DsMonad q => Body -> [Dec] -> DExp -> q DExp
- dsGuards :: DsMonad q => [(Guard, Exp)] -> DExp -> q DExp
- dsDoStmts :: DsMonad q => [Stmt] -> q DExp
- dsComp :: DsMonad q => [Stmt] -> q DExp
- dsClauses :: DsMonad q => Name -> [Clause] -> q [DClause]
- dsBangType :: DsMonad q => BangType -> q DBangType
- dsVarBangType :: DsMonad q => VarBangType -> q DVarBangType
- dsTypeFamilyHead :: DsMonad q => TypeFamilyHead -> q DTypeFamilyHead
- dsFamilyResultSig :: DsMonad q => FamilyResultSig -> q DFamilyResultSig
- dsPatSynDir :: DsMonad q => Name -> PatSynDir -> q DPatSynDir
- module Language.Haskell.TH.Desugar.Sweeten
- expand :: (DsMonad q, Data a) => a -> q a
- expandType :: DsMonad q => DType -> q DType
- reifyWithWarning :: Quasi q => Name -> q Info
- withLocalDeclarations :: DsMonad q => [Dec] -> DsM q a -> q a
- dsReify :: DsMonad q => Name -> q (Maybe DInfo)
- reifyWithLocals_maybe :: DsMonad q => Name -> q (Maybe Info)
- reifyWithLocals :: DsMonad q => Name -> q Info
- reifyFixityWithLocals :: DsMonad q => Name -> q (Maybe Fixity)
- lookupValueNameWithLocals :: DsMonad q => String -> q (Maybe Name)
- lookupTypeNameWithLocals :: DsMonad q => String -> q (Maybe Name)
- mkDataNameWithLocals :: DsMonad q => String -> q Name
- mkTypeNameWithLocals :: DsMonad q => String -> q Name
- reifyNameSpace :: DsMonad q => Name -> q (Maybe NameSpace)
- class Quasi m => DsMonad m where
- data DsM q a
- scExp :: DsMonad q => DExp -> q DExp
- scLetDec :: DsMonad q => DLetDec -> q DLetDec
- module Language.Haskell.TH.Desugar.Subst
- applyDExp :: DExp -> [DExp] -> DExp
- applyDType :: DType -> [DType] -> DType
- dPatToDExp :: DPat -> DExp
- removeWilds :: DsMonad q => DPat -> q DPat
- getDataD :: Quasi q => String -> Name -> q ([TyVarBndr], [Con])
- dataConNameToDataName :: Quasi q => Name -> q Name
- dataConNameToCon :: Quasi q => Name -> q Con
- nameOccursIn :: Data a => Name -> a -> Bool
- allNamesIn :: Data a => a -> [Name]
- flattenDValD :: Quasi q => DLetDec -> q [DLetDec]
- getRecordSelectors :: Quasi q => DType -> [DCon] -> q [DLetDec]
- mkTypeName :: Quasi q => String -> q Name
- mkDataName :: Quasi q => String -> q Name
- newUniqueName :: Quasi q => String -> q Name
- mkTupleDExp :: [DExp] -> DExp
- mkTupleDPat :: [DPat] -> DPat
- maybeDLetE :: [DLetDec] -> DExp -> DExp
- maybeDCaseE :: String -> DExp -> [DMatch] -> DExp
- fvDType :: DType -> Set Name
- tupleDegree_maybe :: String -> Maybe Int
- tupleNameDegree_maybe :: Name -> Maybe Int
- unboxedSumDegree_maybe :: String -> Maybe Int
- unboxedSumNameDegree_maybe :: Name -> Maybe Int
- unboxedTupleDegree_maybe :: String -> Maybe Int
- unboxedTupleNameDegree_maybe :: Name -> Maybe Int
- strictToBang :: Bang -> Bang
- extractBoundNamesStmt :: Stmt -> Set Name
- extractBoundNamesDec :: Dec -> Set Name
- extractBoundNamesPat :: Pat -> Set Name
Desugared data types
Corresponds to TH's Exp
type. Note that DLamE
takes names, not patterns.
Declarations as used in a let
statement.
Corresponds to TH's Pat
type.
Corresponds to TH's Type
type, used to represent
types and kinds.
Corresponds to TH's Pred
data DTyVarBndr Source #
Corresponds to TH's TyVarBndr
Corresponds to TH's Match
type.
Corresponds to TH's Clause
type.
Corresponds to TH's Dec
type.
data DDerivClause Source #
Corresponds to TH's DerivClause
type.
data DerivStrategy :: * #
What the user explicitly requests when deriving an instance.
StockStrategy | A "standard" derived instance |
AnyclassStrategy | -XDeriveAnyClass |
NewtypeStrategy | -XGeneralizedNewtypeDeriving |
data DPatSynDir Source #
Corresponds to TH's PatSynDir
type
DUnidir | pattern P x {<-} p |
DImplBidir | pattern P x {=} p |
DExplBidir [DClause] | pattern P x {<-} p where P x = e |
type DPatSynType = DType Source #
Corresponds to TH's PatSynType
type
Varieties of allowed instance overlap.
Overlappable | May be overlapped by more specific instances |
Overlapping | May overlap a more general instance |
Overlaps | Both |
Incoherent | Both |
data PatSynArgs :: * #
A pattern synonym's argument type.
PrefixPatSyn [Name] | pattern P {x y z} = p |
InfixPatSyn Name Name | pattern {x P y} = p |
RecordPatSyn [Name] | pattern P { {x,y,z} } = p |
Is it a newtype
or a data
type?
data DTypeFamilyHead Source #
Corresponds to TH's TypeFamilyHead
type
data DFamilyResultSig Source #
Corresponds to TH's FamilyResultSig
type
data InjectivityAnn :: * #
Injectivity annotation
Corresponds to TH's Con
type.
DCon [DTyVarBndr] DCxt Name DConFields (Maybe DType) | A GADT result type, if there is one |
data DConFields Source #
A list of fields either for a standard data constructor or a record data constructor.
type DDeclaredInfix = Bool Source #
True
if a constructor is declared infix. For normal ADTs, this means
that is was written in infix style. For example, both of the constructors
below are declared infix.
data Infix = Int Infix
Int | Int :*: Int
Whereas neither of these constructors are declared infix:
data Prefix = Prefix Int Int | (:+:) Int Int
For GADTs, detecting whether a constructor is declared infix is a bit trickier, as one cannot write a GADT constructor "infix-style" like one can for normal ADT constructors. GHC considers a GADT constructor to be declared infix if it meets the following three criteria:
- Its name uses operator syntax (e.g.,
(:*:)
). - It has exactly two fields (without record syntax).
- It has a programmer-specified fixity declaration.
For example, in the following GADT:
infixl 5 :**:, :&&:, :^^:, ActuallyPrefix
data InfixGADT a where
(:**:) :: Int -> b -> InfixGADT (Maybe b) -- Only this one is infix
ActuallyPrefix :: Char -> Bool -> InfixGADT Double
(:&&:) :: { infixGADT1 :: b, infixGADT2 :: Int } -> InfixGADT b :: Int -> Int -> Int -> InfixGADT Int
(:!!:) :: Char -> Char -> InfixGADT Char
Only the (:**:)
constructor is declared infix. The other constructors
are not declared infix, because:
ActuallyPrefix
does not use operator syntax (criterion 1).(:&&:)
uses record syntax (criterion 2).(:^^:)
does not have exactly two fields (criterion 2).(:!!:)
does not have a programmer-specified fixity declaration (criterion 3).
Bang SourceUnpackedness SourceStrictness | C { {-# UNPACK #-} !}a |
data SourceUnpackedness :: * #
NoSourceUnpackedness | C a |
SourceNoUnpack | C { {-# NOUNPACK #-} } a |
SourceUnpack | C { {-# UNPACK #-} } a |
data SourceStrictness :: * #
NoSourceStrictness | C a |
SourceLazy | C {~}a |
SourceStrict | C {!}a |
Corresponds to TH's Foreign
type.
Corresponds to TH's Pragma
type.
Corresponds to TH's RuleBndr
type.
Corresponds to TH's TySynEqn
type (to store type family equations).
Corresponds to TH's Info
type.
DTyConI DDec (Maybe [DInstanceDec]) | |
DVarI Name DType (Maybe Name) | The |
DTyVarI Name DKind | |
DPrimTyConI Name Int Bool | The |
DPatSynI Name DPatSynType |
type DInstanceDec Source #
= DDec | Guaranteed to be an instance declaration |
Role annotations
NominalR | nominal |
RepresentationalR | representational |
PhantomR | phantom |
InferR | _ |
The Desugar
class
Main desugaring functions
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 Dec
s that can appear in a let expression
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.
dsDec :: DsMonad q => Dec -> q [DDec] Source #
Desugar a single Dec
, perhaps producing multiple DDec
s
dsDerivClause :: DsMonad q => DerivClause -> q DDerivClause Source #
Desugar a DerivClause
.
dsLetDec :: DsMonad q => Dec -> q [DLetDec] Source #
Desugar a single Dec
, perhaps producing multiple DLetDec
s
:: DsMonad q | |
=> Name | Name of the scrutinee, which must be a bare var |
-> [Match] | Matches of the |
-> q [DMatch] |
Desugar a list of matches for a case
statement
:: DsMonad q | |
=> Body | body to desugar |
-> [Dec] | "where" declarations |
-> DExp | what to do if the guards don't match |
-> q DExp |
Desugar a Body
:: DsMonad q | |
=> [(Guard, Exp)] | Guarded expressions |
-> DExp | What to do if none of the guards match |
-> q DExp |
Desugar guarded expressions
Desugar clauses to a function definition
dsBangType :: DsMonad q => BangType -> q DBangType Source #
Desugar a BangType
(or a StrictType
, if you're old-fashioned)
dsVarBangType :: DsMonad q => VarBangType -> q DVarBangType Source #
Desugar a VarBangType
(or a VarStrictType
, if you're old-fashioned)
dsTypeFamilyHead :: DsMonad q => TypeFamilyHead -> q DTypeFamilyHead Source #
Desugar a TypeFamilyHead
dsFamilyResultSig :: DsMonad q => FamilyResultSig -> q DFamilyResultSig Source #
Desugar a FamilyResultSig
dsPatSynDir :: DsMonad q => Name -> PatSynDir -> q DPatSynDir Source #
Desugar a PatSynDir
. (Available only with GHC 8.2+)
Converting desugared AST back to TH AST
Expanding type synonyms
expandType :: DsMonad q => DType -> q DType Source #
Expands all type synonyms in a desugared type. Also expands open type family applications. (In GHCs before 7.10, this part does not work if there are any 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.
Reification
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
Dec
s 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.
reifyFixityWithLocals :: DsMonad q => Name -> q (Maybe Fixity) Source #
Like reifyWithLocals_maybe
, but for fixities. Note that a return of
Nothing
might mean that the name is not in scope, or it might mean
that the name has no assigned fixity. (Use reifyWithLocals_maybe
if
you really need to tell the difference.)
lookupValueNameWithLocals :: DsMonad q => String -> q (Maybe Name) Source #
Like lookupValueName
from Template Haskell, but looks also in Names
of
not-yet-typechecked declarations. To establish this list of not-yet-typechecked
declarations, use withLocalDeclarations
. Returns Nothing
if no value
with the same name can be found.
lookupTypeNameWithLocals :: DsMonad q => String -> q (Maybe Name) Source #
Like lookupTypeName
from Template Haskell, but looks also in Names
of
not-yet-typechecked declarations. To establish this list of not-yet-typechecked
declarations, use withLocalDeclarations
. Returns Nothing
if no type
with the same name can be found.
mkDataNameWithLocals :: DsMonad q => String -> q Name Source #
Like TH's lookupValueName
, but if this name is not bound, then we assume
it is declared in the current module.
Unlike mkDataName
, this also consults the local declarations in scope when
determining if the name is currently bound.
mkTypeNameWithLocals :: DsMonad 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.
Unlike mkTypeName
, this also consults the local declarations in scope when
determining if the name is currently bound.
reifyNameSpace :: DsMonad q => Name -> q (Maybe NameSpace) Source #
Determines a Name
's NameSpace
. If the NameSpace
is attached to
the Name
itself (i.e., it is unambiguous), then that NameSpace
is
immediately returned. Otherwise, reification is used to lookup up the
NameSpace
(consulting local declarations if necessary).
Note that if a Name
lives in two different NameSpaces
(which can
genuinely happen--for instance,
, where mkName
"=="==
is both
a function and a type family), then this function will simply return
whichever NameSpace
is discovered first via reification. If you wish
to find a Name
in a particular NameSpace
, use the
lookupValueNameWithLocals
or lookupTypeNameWithLocals
functions.
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.
A convenient implementation of the DsMonad
class. Use by calling
withLocalDeclarations
.
Nested pattern flattening
Capture-avoiding substitution and utilities
Utility functions
removeWilds :: DsMonad q => DPat -> q DPat Source #
Remove all wildcards from a pattern, replacing any wildcard with a fresh variable
:: Quasi q | |
=> String | Print this out on failure |
-> Name | Name of the datatype ( |
-> q ([TyVarBndr], [Con]) |
Extract the TyVarBndr
s 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 DValD
s 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.
Produces DLetDec
s representing the record selector functions from
the provided DCon
s.
Note that if the same record selector appears in multiple constructors,
getRecordSelectors
will return only one binding for that selector.
For example, if you had:
data X = X1 {y :: Symbol} | X2 {y :: Symbol}
Then calling getRecordSelectors
on [X1, X2]
will return:
[ DSigD y (DAppT (DAppT DArrowT (DConT X)) (DConT Symbol)) , DFunD y [ DClause [DConPa X1 [DVarPa field]] (DVarE field) , DClause [DConPa X2 [DVarPa field]] (DVarE field) ] ]
instead of returning one binding for X1
and another binding for X2
.
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 nameBase
s. Precondition: the string is a valid Haskell
alphanumeric identifier (could be upper- or lower-case).
mkTupleDExp :: [DExp] -> DExp Source #
mkTupleDPat :: [DPat] -> DPat Source #
maybeDCaseE :: String -> DExp -> [DMatch] -> DExp Source #
If matches is non-empty, make a case statement; otherwise make an error statement
unboxedTupleNameDegree_maybe :: Name -> Maybe Int Source #
Extract the degree of an unboxed tuple name
strictToBang :: Bang -> Bang Source #