Copyright | (C) 2014 Richard Eisenberg |
---|---|
License | BSD-style (see LICENSE) |
Maintainer | Ryan Scott |
Stability | experimental |
Portability | non-portable |
Safe Haskell | None |
Language | Haskell2010 |
Desugars full Template Haskell syntax into a smaller core syntax for further processing.
Synopsis
- 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] (Maybe DKind) [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] (Maybe DKind)
- | DDataInstD NewOrData DCxt Name [DType] (Maybe DKind) [DCon] [DDerivClause]
- | DTySynInstD Name DTySynEqn
- | DRoleAnnotD Name [Role]
- | DStandaloneDerivD (Maybe DDerivStrategy) DCxt DType
- | DDefaultSigD Name DType
- | DPatSynD Name PatSynArgs DPatSynDir DPat
- | DPatSynSigD Name DPatSynType
- data DDerivClause = DDerivClause (Maybe DDerivStrategy) DCxt
- data DDerivStrategy
- 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 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 => [DTyVarBndr] -> DType -> 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 :: DsMonad q => String -> Name -> q ([TyVarBndr], [Con])
- dataConNameToDataName :: DsMonad q => Name -> q Name
- dataConNameToCon :: DsMonad 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
- mkDLamEFromDPats :: DsMonad q => [DPat] -> DExp -> q 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
- isTypeKindName :: Name -> Bool
- typeKindName :: Name
- unravel :: DType -> ([DTyVarBndr], [DPred], [DType], DType)
- conExistentialTvbs :: DsMonad q => DType -> DCon -> q [DTyVarBndr]
- mkExtraDKindBinders :: DsMonad q => DKind -> q [DTyVarBndr]
- dTyVarBndrToDType :: DTyVarBndr -> DType
- toposortTyVarsOf :: [DType] -> [DTyVarBndr]
- 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.
DVarE Name | |
DConE Name | |
DLitE Lit | |
DAppE DExp DExp | |
DAppTypeE DExp DType | |
DLamE [Name] DExp | |
DCaseE DExp [DMatch] | |
DLetE [DLetDec] DExp | |
DSigE DExp DType | |
DStaticE DExp |
Instances
Declarations as used in a let
statement.
Instances
Corresponds to TH's Pat
type.
Instances
Corresponds to TH's Type
type, used to represent
types and kinds.
DForallT [DTyVarBndr] DCxt DType | |
DAppT DType DType | |
DSigT DType DKind | |
DVarT Name | |
DConT Name | |
DArrowT | |
DLitT TyLit | |
DWildCardT |
Instances
Corresponds to TH's Pred
DForallPr [DTyVarBndr] DCxt DPred | |
DAppPr DPred DType | |
DSigPr DPred DKind | |
DVarPr Name | |
DConPr Name | |
DWildCardPr |
Instances
data DTyVarBndr Source #
Corresponds to TH's TyVarBndr
Instances
Corresponds to TH's Match
type.
Instances
Data DMatch Source # | |
Defined in Language.Haskell.TH.Desugar.AST gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> DMatch -> c DMatch # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c DMatch # toConstr :: DMatch -> Constr # dataTypeOf :: DMatch -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c DMatch) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c DMatch) # gmapT :: (forall b. Data b => b -> b) -> DMatch -> DMatch # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> DMatch -> r # gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> DMatch -> r # gmapQ :: (forall d. Data d => d -> u) -> DMatch -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> DMatch -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> DMatch -> m DMatch # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> DMatch -> m DMatch # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> DMatch -> m DMatch # | |
Show DMatch Source # | |
Generic DMatch Source # | |
Lift DMatch # | |
type Rep DMatch Source # | |
Defined in Language.Haskell.TH.Desugar.AST type Rep DMatch = D1 (MetaData "DMatch" "Language.Haskell.TH.Desugar.AST" "th-desugar-1.9-9UPecqpFTe7J0l3WpXzg5W" False) (C1 (MetaCons "DMatch" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 DPat) :*: S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 DExp))) |
Corresponds to TH's Clause
type.
Instances
Data DClause Source # | |
Defined in Language.Haskell.TH.Desugar.AST gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> DClause -> c DClause # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c DClause # toConstr :: DClause -> Constr # dataTypeOf :: DClause -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c DClause) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c DClause) # gmapT :: (forall b. Data b => b -> b) -> DClause -> DClause # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> DClause -> r # gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> DClause -> r # gmapQ :: (forall d. Data d => d -> u) -> DClause -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> DClause -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> DClause -> m DClause # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> DClause -> m DClause # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> DClause -> m DClause # | |
Show DClause Source # | |
Generic DClause Source # | |
Lift DClause # | |
type Rep DClause Source # | |
Defined in Language.Haskell.TH.Desugar.AST type Rep DClause = D1 (MetaData "DClause" "Language.Haskell.TH.Desugar.AST" "th-desugar-1.9-9UPecqpFTe7J0l3WpXzg5W" False) (C1 (MetaCons "DClause" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 [DPat]) :*: S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 DExp))) |
Corresponds to TH's Dec
type.
Instances
data DDerivClause Source #
Corresponds to TH's DerivClause
type.
Instances
data DDerivStrategy Source #
Corresponds to TH's DerivStrategy
type.
DStockStrategy | A "standard" derived instance |
DAnyclassStrategy | -XDeriveAnyClass |
DNewtypeStrategy | -XGeneralizedNewtypeDeriving |
DViaStrategy DType | -XDerivingVia |
Instances
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 |
Instances
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 |
Instances
Eq Overlap | |
Data Overlap | |
Defined in Language.Haskell.TH.Syntax gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Overlap -> c Overlap # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c Overlap # toConstr :: Overlap -> Constr # dataTypeOf :: Overlap -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c Overlap) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Overlap) # gmapT :: (forall b. Data b => b -> b) -> Overlap -> Overlap # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Overlap -> r # gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Overlap -> r # gmapQ :: (forall d. Data d => d -> u) -> Overlap -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> Overlap -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> Overlap -> m Overlap # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Overlap -> m Overlap # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Overlap -> m Overlap # | |
Ord Overlap | |
Show Overlap | |
Generic Overlap | |
type Rep Overlap | |
Defined in Language.Haskell.TH.Syntax type Rep Overlap = D1 (MetaData "Overlap" "Language.Haskell.TH.Syntax" "template-haskell" False) ((C1 (MetaCons "Overlappable" PrefixI False) (U1 :: * -> *) :+: C1 (MetaCons "Overlapping" PrefixI False) (U1 :: * -> *)) :+: (C1 (MetaCons "Overlaps" PrefixI False) (U1 :: * -> *) :+: C1 (MetaCons "Incoherent" PrefixI False) (U1 :: * -> *))) |
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 |
Instances
Is it a newtype
or a data
type?
Instances
Eq NewOrData Source # | |
Data NewOrData Source # | |
Defined in Language.Haskell.TH.Desugar.AST gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> NewOrData -> c NewOrData # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c NewOrData # toConstr :: NewOrData -> Constr # dataTypeOf :: NewOrData -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c NewOrData) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c NewOrData) # gmapT :: (forall b. Data b => b -> b) -> NewOrData -> NewOrData # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> NewOrData -> r # gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> NewOrData -> r # gmapQ :: (forall d. Data d => d -> u) -> NewOrData -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> NewOrData -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> NewOrData -> m NewOrData # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> NewOrData -> m NewOrData # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> NewOrData -> m NewOrData # | |
Show NewOrData Source # | |
Generic NewOrData Source # | |
Lift NewOrData # | |
type Rep NewOrData Source # | |
data DTypeFamilyHead Source #
Corresponds to TH's TypeFamilyHead
type
Instances
data DFamilyResultSig Source #
Corresponds to TH's FamilyResultSig
type
Instances
data InjectivityAnn #
Injectivity annotation
Instances
Corresponds to TH's Con
type. Unlike Con
, all DCon
s reflect GADT
syntax. This is beneficial for th-desugar
's since it means
that all data type declarations can support explicit return kinds, so
one does not need to represent them with something like
,
since Haskell98-style data declaration syntax isn't used. Accordingly,
there are some differences between Maybe
DKind
DCon
and Con
to keep in mind:
- Unlike
ForallC
, where the meaning of theTyVarBndr
s changes depending on whether it's followed by 'GadtC'/'RecGadtC' or not, the meaning of theDTyVarBndr
s in aDCon
is always the same: it is the list of universally and existentially quantified type variables. Note that it is not guaranteed that one set of type variables will appear before the other. - A
DCon
always has an explicit return type.
DCon [DTyVarBndr] DCxt Name DConFields DType | The GADT result type |
Instances
Data DCon Source # | |
Defined in Language.Haskell.TH.Desugar.AST gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> DCon -> c DCon # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c DCon # dataTypeOf :: DCon -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c DCon) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c DCon) # gmapT :: (forall b. Data b => b -> b) -> DCon -> DCon # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> DCon -> r # gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> DCon -> r # gmapQ :: (forall d. Data d => d -> u) -> DCon -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> DCon -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> DCon -> m DCon # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> DCon -> m DCon # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> DCon -> m DCon # | |
Show DCon Source # | |
Generic DCon Source # | |
Lift DCon # | |
type Rep DCon Source # | |
Defined in Language.Haskell.TH.Desugar.AST type Rep DCon = D1 (MetaData "DCon" "Language.Haskell.TH.Desugar.AST" "th-desugar-1.9-9UPecqpFTe7J0l3WpXzg5W" False) (C1 (MetaCons "DCon" PrefixI False) ((S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 [DTyVarBndr]) :*: S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 DCxt)) :*: (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 Name) :*: (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 DConFields) :*: S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 DType))))) |
data DConFields Source #
A list of fields either for a standard data constructor or a record data constructor.
Instances
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 |
Instances
Eq Bang | |
Data Bang | |
Defined in Language.Haskell.TH.Syntax gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Bang -> c Bang # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c Bang # dataTypeOf :: Bang -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c Bang) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Bang) # gmapT :: (forall b. Data b => b -> b) -> Bang -> Bang # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Bang -> r # gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Bang -> r # gmapQ :: (forall d. Data d => d -> u) -> Bang -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> Bang -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> Bang -> m Bang # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Bang -> m Bang # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Bang -> m Bang # | |
Ord Bang | |
Show Bang | |
Generic Bang | |
Ppr Bang | |
type Rep Bang | |
Defined in Language.Haskell.TH.Syntax type Rep Bang = D1 (MetaData "Bang" "Language.Haskell.TH.Syntax" "template-haskell" False) (C1 (MetaCons "Bang" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 SourceUnpackedness) :*: S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 SourceStrictness))) |
data SourceUnpackedness #
NoSourceUnpackedness | C a |
SourceNoUnpack | C { {-# NOUNPACK #-} } a |
SourceUnpack | C { {-# UNPACK #-} } a |
Instances
data SourceStrictness #
NoSourceStrictness | C a |
SourceLazy | C {~}a |
SourceStrict | C {!}a |
Instances
Corresponds to TH's Foreign
type.
Instances
Corresponds to TH's Pragma
type.
Instances
Corresponds to TH's RuleBndr
type.
Instances
Data DRuleBndr Source # | |
Defined in Language.Haskell.TH.Desugar.AST gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> DRuleBndr -> c DRuleBndr # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c DRuleBndr # toConstr :: DRuleBndr -> Constr # dataTypeOf :: DRuleBndr -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c DRuleBndr) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c DRuleBndr) # gmapT :: (forall b. Data b => b -> b) -> DRuleBndr -> DRuleBndr # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> DRuleBndr -> r # gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> DRuleBndr -> r # gmapQ :: (forall d. Data d => d -> u) -> DRuleBndr -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> DRuleBndr -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> DRuleBndr -> m DRuleBndr # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> DRuleBndr -> m DRuleBndr # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> DRuleBndr -> m DRuleBndr # | |
Show DRuleBndr Source # | |
Generic DRuleBndr Source # | |
Lift DRuleBndr # | |
type Rep DRuleBndr Source # | |
Defined in Language.Haskell.TH.Desugar.AST type Rep DRuleBndr = D1 (MetaData "DRuleBndr" "Language.Haskell.TH.Desugar.AST" "th-desugar-1.9-9UPecqpFTe7J0l3WpXzg5W" False) (C1 (MetaCons "DRuleVar" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 Name)) :+: C1 (MetaCons "DTypedRuleVar" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 Name) :*: S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 DType))) |
Corresponds to TH's TySynEqn
type (to store type family equations).
Instances
Data DTySynEqn Source # | |
Defined in Language.Haskell.TH.Desugar.AST gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> DTySynEqn -> c DTySynEqn # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c DTySynEqn # toConstr :: DTySynEqn -> Constr # dataTypeOf :: DTySynEqn -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c DTySynEqn) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c DTySynEqn) # gmapT :: (forall b. Data b => b -> b) -> DTySynEqn -> DTySynEqn # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> DTySynEqn -> r # gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> DTySynEqn -> r # gmapQ :: (forall d. Data d => d -> u) -> DTySynEqn -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> DTySynEqn -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> DTySynEqn -> m DTySynEqn # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> DTySynEqn -> m DTySynEqn # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> DTySynEqn -> m DTySynEqn # | |
Show DTySynEqn Source # | |
Generic DTySynEqn Source # | |
Lift DTySynEqn # | |
type Rep DTySynEqn Source # | |
Defined in Language.Haskell.TH.Desugar.AST type Rep DTySynEqn = D1 (MetaData "DTySynEqn" "Language.Haskell.TH.Desugar.AST" "th-desugar-1.9-9UPecqpFTe7J0l3WpXzg5W" False) (C1 (MetaCons "DTySynEqn" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 [DType]) :*: S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 DType))) |
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 |
Instances
type DInstanceDec Source #
= DDec | Guaranteed to be an instance declaration |
Role annotations
NominalR | nominal |
RepresentationalR | representational |
PhantomR | phantom |
InferR | _ |
Instances
Eq Role | |
Data Role | |
Defined in Language.Haskell.TH.Syntax gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Role -> c Role # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c Role # dataTypeOf :: Role -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c Role) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Role) # gmapT :: (forall b. Data b => b -> b) -> Role -> Role # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Role -> r # gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Role -> r # gmapQ :: (forall d. Data d => d -> u) -> Role -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> Role -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> Role -> m Role # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Role -> m Role # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Role -> m Role # | |
Ord Role | |
Show Role | |
Generic Role | |
Ppr Role | |
type Rep Role | |
Defined in Language.Haskell.TH.Syntax type Rep Role = D1 (MetaData "Role" "Language.Haskell.TH.Syntax" "template-haskell" False) ((C1 (MetaCons "NominalR" PrefixI False) (U1 :: * -> *) :+: C1 (MetaCons "RepresentationalR" PrefixI False) (U1 :: * -> *)) :+: (C1 (MetaCons "PhantomR" PrefixI False) (U1 :: * -> *) :+: C1 (MetaCons "InferR" PrefixI False) (U1 :: * -> *))) |
Instances
Eq AnnTarget | |
Data AnnTarget | |
Defined in Language.Haskell.TH.Syntax gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> AnnTarget -> c AnnTarget # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c AnnTarget # toConstr :: AnnTarget -> Constr # dataTypeOf :: AnnTarget -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c AnnTarget) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c AnnTarget) # gmapT :: (forall b. Data b => b -> b) -> AnnTarget -> AnnTarget # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> AnnTarget -> r # gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> AnnTarget -> r # gmapQ :: (forall d. Data d => d -> u) -> AnnTarget -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> AnnTarget -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> AnnTarget -> m AnnTarget # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> AnnTarget -> m AnnTarget # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> AnnTarget -> m AnnTarget # | |
Ord AnnTarget | |
Defined in Language.Haskell.TH.Syntax | |
Show AnnTarget | |
Generic AnnTarget | |
type Rep AnnTarget | |
Defined in Language.Haskell.TH.Syntax type Rep AnnTarget = D1 (MetaData "AnnTarget" "Language.Haskell.TH.Syntax" "template-haskell" False) (C1 (MetaCons "ModuleAnnotation" PrefixI False) (U1 :: * -> *) :+: (C1 (MetaCons "TypeAnnotation" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 Name)) :+: C1 (MetaCons "ValueAnnotation" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (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.
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
:: DsMonad q | |
=> [DTyVarBndr] | The universally quantified type variables (used if desugaring a non-GADT constructor). |
-> DType | The original data declaration's type (used if desugaring a non-GADT constructor). |
-> Con | |
-> q [DCon] |
Desugar a single Con
.
Because we always desugar Con
s to GADT syntax (see the documentation for
DCon
), it is not always possible to desugar with just a Con
alone.
For instance, we must desugar:
data Foo a = forall b. MkFoo b
To this:
data Foo a :: Type where MkFoo :: forall a b. b -> Foo a
If our only argument was forall b. MkFoo b
, it would be somewhat awkward
to figure out (1) what the set of universally quantified type variables
([a]
) was, and (2) what the return type (Foo a
) was. For this reason,
we require passing these as arguments. (If we desugar an actual GADT
constructor, these arguments are ignored.)
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.
Instances
DsMonad IO Source # | |
Defined in Language.Haskell.TH.Desugar.Reify localDeclarations :: IO [Dec] Source # | |
DsMonad Q Source # | |
Defined in Language.Haskell.TH.Desugar.Reify localDeclarations :: Q [Dec] Source # | |
Quasi q => DsMonad (DsM q) Source # | |
Defined in Language.Haskell.TH.Desugar.Reify localDeclarations :: DsM q [Dec] Source # | |
DsMonad m => DsMonad (StateT s m) Source # | |
Defined in Language.Haskell.TH.Desugar.Reify localDeclarations :: StateT s m [Dec] Source # | |
(DsMonad m, Monoid w) => DsMonad (WriterT w m) Source # | |
Defined in Language.Haskell.TH.Desugar.Reify localDeclarations :: WriterT w m [Dec] Source # | |
DsMonad m => DsMonad (ReaderT r m) Source # | |
Defined in Language.Haskell.TH.Desugar.Reify localDeclarations :: ReaderT r m [Dec] Source # | |
(DsMonad m, Monoid w) => DsMonad (RWST r w s m) Source # | |
Defined in Language.Haskell.TH.Desugar.Reify localDeclarations :: RWST r w s m [Dec] Source # |
A convenient implementation of the DsMonad
class. Use by calling
withLocalDeclarations
.
Instances
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
:: DsMonad 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 :: DsMonad q => Name -> q Name Source #
From the name of a data constructor, retrive the datatype definition it is a part of.
dataConNameToCon :: DsMonad 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
.
getRecordSelectors
attempts to filter out "naughty" record selectors
whose types mention existentially quantified type variables. But see the
documentation for conExistentialTvbs
for limitations to this approach.
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 #
isTypeKindName :: Name -> Bool Source #
typeKindName :: Name Source #
unravel :: DType -> ([DTyVarBndr], [DPred], [DType], DType) Source #
Decompose a function type into its type variables, its context, its argument types, and its result type.
:: DsMonad q | |
=> DType | The type of the original data declaration |
-> DCon | |
-> q [DTyVarBndr] |
Returns all of a constructor's existentially quantified type variable binders.
Detecting the presence of existentially quantified type variables in the context of Template Haskell is quite involved. Here is an example that we will use to explain how this works:
data family Foo a b data instance Foo (Maybe a) b where MkFoo :: forall x y z. x -> y -> z -> Foo (Maybe x) [z]
In MkFoo
, x
is universally quantified, whereas y
and z
are
existentially quantified. Note that MkFoo
desugars (in Core) to
something like this:
data instance Foo (Maybe a) b where MkFoo :: forall a b y z. (b ~ [z]). a -> y -> z -> Foo (Maybe a) b
Here, we can see that a
appears in the desugared return type (it is a
simple alpha-renaming of x
), so it is universally quantified. On the other
hand, neither y
nor z
appear in the desugared return type, so they are
existentially quantified.
This analysis would not have been possible without knowing what the original
data declaration's type was (in this case, Foo (Maybe a) b
), which is why
we require it as an argument. Our algorithm for detecting existentially
quantified variables is not too different from what was described above:
we match the constructor's return type with the original data type, forming
a substitution, and check which quantified variables are not part of the
domain of the substitution.
Be warned: this may overestimate which variables are existentially quantified when kind variables are involved. For instance, consider this example:
data S k (a :: k) data T a where MkT :: forall k (a :: k). { foo :: Proxy (a :: k), bar :: S k a } -> T a
Here, the kind variable k
does not appear syntactically in the return type
T a
, so conExistentialTvbs
would mistakenly flag k
as existential.
There are various tricks we could employ to improve this, but ultimately,
making this behave correctly with respect to PolyKinds
100% of the time
would amount to performing kind inference in Template Haskell, which is
quite difficult. For the sake of simplicity, we have decided to stick with
a dumb-but-predictable syntactic check.
mkExtraDKindBinders :: DsMonad q => DKind -> q [DTyVarBndr] Source #
Create new kind variable binder names corresponding to the return kind of a data type. This is useful when you have a data type like:
data Foo :: forall k. k -> Type -> Type where ...
But you want to be able to refer to the type Foo a b
.
mkExtraDKindBinders
will take the kind forall k. k -> Type -> Type
,
discover that is has two visible argument kinds, and return as a result
two new kind variable binders [a :: k, b :: Type]
, where a
and b
are fresh type variable names.
This expands kind synonyms if necessary.
dTyVarBndrToDType :: DTyVarBndr -> DType Source #
Convert a DTyVarBndr
into a DType
toposortTyVarsOf :: [DType] -> [DTyVarBndr] Source #
Take a list of DType
s, find their free variables, and sort them in
reverse topological order to ensure that they are well scoped.
On older GHCs, this takes measures to avoid returning explicitly bound
kind variables, which was not possible before TypeInType
.