HORIZON HASKELLDocslts/ghc-9.10.x248f8f02026-10-05Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · 248f8f0 · 2026-10-05

Moduleth-desugar-1.17Haskell2010

Language.Haskell.TH.Desugar

Desugars full Template Haskell syntax into a smaller core syntax for further processing.

  • 54 types
  • 2 classes
  • 104 values
  • Packageth-desugar-1.17
  • Exports160
  • LanguageHaskell2010
  • LicenceBSD-3-Clause
  • SourceDesugar.hs

Desugared data types

44 declarations
datadata DExp
#
Instances7Eq, Data, Show, Generic, Lift, Desugar, …
datadata DLetDec
#

Declarations as used in a let statement.

Instances6Eq, Data, Show, Generic, Lift, Rep
datadata NamespaceSpecifier
#

A way to specify a namespace to look in when GHC needs to find a name's source

Constructors

  • NoNamespaceSpecifier

    Name may be everything; If there are two names in different namespaces, then consider both

  • TypeNamespaceSpecifier

    Name should be a type-level entity, such as a data type, type alias, type family, type class, or type variable

  • DataNamespaceSpecifier

    Name should be a term-level entity, such as a function, data constructor, or pattern synonym

Instances7Eq, Data, Ord, Show, Generic, Lift, …
datadata DPat
#

Corresponds to TH's Pat type.

Constructors

  • DLitP Lit
  • DVarP Name
  • DConP Name [DType] [DPat]
  • DTildeP DPat
  • DBangP DPat
  • DSigP DPat DType
  • DWildP
  • DTypeP DType

    Note that th-desugar only has partial support for desugaring embedded type patterns. In particular, th-desugar supports desugaring embedded type patterns in function clauses, but not in lambda expressions, \case expressions, or \cases expressions. See the "Known limitations" section of the th-desugar README for more details.

  • DInvisP DType

    Note that th-desugar only has partial support for desugaring invisible type patterns. In particular, th-desugar supports desugaring invisible type patterns in function clauses, but not in lambda expressions or \cases expressions. See the "Known limitations" section of the th-desugar README for more details.

Instances6Eq, Data, Show, Generic, Lift, Rep
datadata DType
#
Instances8Eq, Data, Show, Generic, Lift, Desugar, …
datadata DForallTelescope
#

The type variable binders in a forall.

Constructors

Instances6Eq, Data, Show, Generic, Lift, Rep
typetype DKind = DType
#

Kinds are types. Corresponds to TH's Kind

typetype DCxt = [DPred]
#

Corresponds to TH's Cxt

typetype DPred = DType
#

Predicates are types. Corresponds to TH's Pred

datadata DTyVarBndr flag
#

Corresponds to TH's TyVarBndr

Constructors

Instances10Functor, Foldable, Traversable, Lift, Eq, Data, …
datadata Specificity
#
Instances9Eq, Data, Ord, Show, Generic, DefaultBndrFlag, …
datadata BndrVis
#

Constructors

Instances9Eq, Data, Ord, Show, Generic, DefaultBndrFlag, …
  • Eq BndrVisDefined in template-haskell-2.22.0.0 · Language.Haskell.TH.Syntax
  • Data BndrVisDefined in template-haskell-2.22.0.0 · Language.Haskell.TH.Syntax
  • Ord BndrVisDefined in template-haskell-2.22.0.0 · Language.Haskell.TH.Syntax
  • Show BndrVisDefined in template-haskell-2.22.0.0 · Language.Haskell.TH.Syntax
  • Generic BndrVisDefined in template-haskell-2.22.0.0 · Language.Haskell.TH.Syntax
  • DefaultBndrFlag BndrVisDefined in template-haskell-2.22.0.0 · Language.Haskell.TH.Lib
  • PprFlag BndrVisDefined in template-haskell-2.22.0.0 · Language.Haskell.TH.Ppr
  • Lift BndrVisDefined in th-orphans-0.13.16 · Language.Haskell.TH.Instances · orphan
  • type Rep BndrVis = D1 ('MetaData "BndrVis" "Language.Haskell.TH.Syntax" "template-haskell" 'False) (C1 ('MetaCons "BndrReq" 'PrefixI 'False) U1 :+: C1 ('MetaCons "BndrInvis" 'PrefixI 'False) U1)Defined in template-haskell-2.22.0.0 · Language.Haskell.TH.Syntax
datadata DMatch
#

Corresponds to TH's Match type.

Constructors

Instances6Eq, Data, Show, Generic, Lift, Rep
datadata DClause
#

Corresponds to TH's Clause type.

Constructors

Instances6Eq, Data, Show, Generic, Lift, Rep
datadata DDec
#

Corresponds to TH's Dec type.

Constructors

Instances7Eq, Data, Show, Generic, Lift, Desugar, …
datadata DDerivClause
#

Corresponds to TH's DerivClause type.

Instances6Eq, Data, Show, Generic, Lift, Rep
datadata DDerivStrategy
#

Corresponds to TH's DerivStrategy type.

Constructors

Instances6Eq, Data, Show, Generic, Lift, Rep
datadata DPatSynDir
#

Corresponds to TH's PatSynDir type

Constructors

Instances6Eq, Data, Show, Generic, Lift, Rep
datadata Overlap
#

Varieties of allowed instance overlap.

Constructors

Instances7Eq, Data, Ord, Show, Generic, Lift, …
datadata PatSynArgs
#

A pattern synonym's argument type.

Constructors

Instances8Eq, Data, Ord, Show, Generic, Ppr, …
datadata DataFlavor
#

Is a data type or data instance declaration a newtype declaration, a data declaration, or a type data declaration?

Constructors

Instances6Eq, Data, Show, Generic, Lift, Rep
datadata DTypeFamilyHead
#
Instances6Eq, Data, Show, Generic, Lift, Rep
datadata DFamilyResultSig
#

Corresponds to TH's FamilyResultSig type

Instances6Eq, Data, Show, Generic, Lift, Rep
datadata InjectivityAnn
#

Injectivity annotation

Constructors

Instances8Eq, Data, Ord, Show, Generic, Ppr, …
datadata DCon
#

Corresponds to TH's Con type. Unlike Con, all DCons 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 Maybe DKind, since Haskell98-style data declaration syntax isn't used. Accordingly, there are some differences between DCon and Con to keep in mind:

  • Unlike ForallC, where the meaning of the TyVarBndrs changes depending on whether it's followed by GadtC/RecGadtC or not, the meaning of the DTyVarBndrs in a DCon 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.

Constructors

Instances6Eq, Data, Show, Generic, Lift, Rep
datadata DConFields
#

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

Instances6Eq, Data, Show, Generic, Lift, Rep
typetype DDeclaredInfix = Bool
#

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:

  1. Its name uses operator syntax (e.g., (:*:)).

  2. It has exactly two fields (without record syntax).

  3. 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).

datadata Bang
#

Constructors

Instances8Eq, Data, Ord, Show, Generic, Ppr, …
datadata SourceUnpackedness
#

SourceUnpackedness corresponds to unpack annotations found in the source code.

This may not agree with the annotations returned by reifyConStrictness. See reifyConStrictness for more information.

Constructors

Instances8Eq, Data, Ord, Show, Generic, Ppr, …
datadata SourceStrictness
#

SourceStrictness corresponds to strictness annotations found in the source code.

This may not agree with the annotations returned by reifyConStrictness. See reifyConStrictness for more information.

Constructors

Instances8Eq, Data, Ord, Show, Generic, Ppr, …
datadata DForeign
#

Corresponds to TH's Foreign type.

Instances6Eq, Data, Show, Generic, Lift, Rep
datadata DPragma
#
Instances6Eq, Data, Show, Generic, Lift, Rep
datadata DRuleBndr
#

Corresponds to TH's RuleBndr type.

Instances6Eq, Data, Show, Generic, Lift, Rep
datadata DTySynEqn
#

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

Instances6Eq, Data, Show, Generic, Lift, Rep
datadata DInfo
#

Corresponds to TH's Info type.

Constructors

Instances6Eq, Data, Show, Generic, Lift, Rep
datadata Role
#

Role annotations

Constructors

Instances8Eq, Data, Ord, Show, Generic, Ppr, …
datadata AnnTarget
#
Instances7Eq, Data, Ord, Show, Generic, Lift, …

The Desugar class

1 declaration
classclass Desugar th ds | ds -> th where
#

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 we define the following instances on old versions of GHC:

instance Desugar TyVarBndrSpec DTyVarBndrSpec
instance Desugar TyVarBndrUnit DTyVarBndrUnit

Prior to GHC 9.0, TyVarBndrSpec and TyVarBndrUnit are simply type synonyms for TyVarBndr, so making the functional dependencies bidirectional would cause these instances to be rejected.

Methods

Instances6Desugar

Main desugaring functions

17 declarations
valuedsPatOverExp :: DsMonad q => Pat -> DExp -> q (DPat, DExp)
#

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

valuedsPatX :: DsMonad q => Pat -> q (DPat, [(Name, DExp)])
#

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

valuedsCon
  1. :: DsMonad q
  2. => [DTyVarBndrVis]

    The universally quantified type variables (used if desugaring a non-GADT constructor).

  3. -> DType

    The original data declaration's type (used if desugaring a non-GADT constructor).

  4. -> Con
  5. -> q [DCon]
#

Desugar a single Con.

Because we always desugar Cons 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

typetype PatM (q :: Type -> Type) = WriterT [(Name, DExp)] q
#

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.

A backwards-compatible type synonym for the thing representing a single derived class in a deriving clause. (This is a DerivClause, Pred, or Name depending on the GHC version.)

valuedsLetDec :: DsMonad q => Dec -> q ([DLetDec], DExp -> DExp)
#

Desugar a single Dec that can appear in a let expression. This produces the following output:

  • One or more DLetDecs (a single Dec can produce multiple DLetDecs in the event of a value declaration that binds multiple things by way of pattern matching.

  • A function of type DExp -> DExp, which should be applied to the expression immediately following the DLetDecs. This function prepends binding forms for any implicit params that were bound in the argument Dec. (If no implicit params are bound, this is simply the id function.)

For instance, if the argument to dsLetDec is the ?x = 42 part of this expression:

let { ?x = 42 } in ?x

Then the output is:

  • let new_x_val = 42
  • \z -> bindIP @"x" new_x_val z

This way, the expression let { new_x_val = 42 } in bindIP @"x" new_x_val (ip @"x") can be formed. The implicit param binders always come after all the other DLetDecs to support parallel assignment of implicit params.

valuedsMatches
  1. :: DsMonad q
  2. => Name

    Name of the scrutinee, which must be a bare var

  3. -> [Match]

    Matches of the case statement

  4. -> q [DMatch]
#

Desugar a list of matches for a case statement

valuedsBody
  1. :: DsMonad q
  2. => Body

    body to desugar

  3. -> [Dec]

    "where" declarations

  4. -> DExp

    what to do if the guards don't match

  5. -> q DExp
#

Desugar a Body

valuedsClauses
  1. :: DsMonad q
  2. => MatchContext

    The context in which the clauses arise

  3. -> [Clause]

    Clauses to desugar

  4. -> q [DClause]
#

Desugar clauses to a function definition

Converting desugared AST back to TH AST

0 declarations

Expanding type synonyms

2 declarations
valueexpand :: (DsMonad q, Data a) => a -> q a
#

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.

valueexpandType :: DsMonad q => DType -> q DType
#

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

1 declaration
valuereifyWithWarning :: (Quasi q, MonadFail q) => Name -> q Info
#

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.

Local reification

template-haskell reification functions like reify and qReify, as well as th-desugar's reifyWithWarning, only look through declarations that either (1) have already been typechecked in the current module, or (2) are in scope because of imports. We refer to this as global reification. Sometimes, however, you may wish to reify declarations that have been quoted but not yet been typechecked, such as in the following example:

example :: IO ()
example = putStrLn
  $(do decs <- [d| data Foo = MkFoo |]
       info <- reify (mkName "Foo")
       stringE $ pprint info)

Because Foo only exists in a TH quote, it is not available globally. As a result, the call to reify (mkName "Foo") will fail.

To make this sort of example possible, th-desugar extends global reification with local reification. A function that performs local reification (such as dsReify, reifyWithLocals, or similar functions that have a DsMonad context) looks through both typechecked (or imported) declarations and quoted declarations that are currently in scope. One can add quoted declarations in the current scope by using the withLocalDeclarations function. Here is an example of how to repair the example above using withLocalDeclarations:

example2 :: IO ()
example2 = putStrLn
  $(do decs <- [d| data Foo = MkFoo |]
       info <- withLocalDeclarations decs $
                 reifyWithLocals (mkName "Foo")
       stringE $ pprint info)

Note that withLocalDeclarations should only be used to add quoted declarations with names that are not duplicates of existing global or local declarations. Adding duplicate declarations through withLocalDeclarations is undefined behavior and should be avoided. This is unlikely to happen if you are only using withLocalDeclarations in conjunction with TH quotes, however. For instance, this is not an example of duplicate declarations:

data T = MkT1

$(do decs <- [d| data T = MkT2 |]
     info <- withLocalDeclarations decs ...
     ...)

The quoted data T = MkT2 does not conflict with the top-level data T = Mk1 since declaring a data type within TH quotes gives it a fresh, unique name that distinguishes it from any other data types already in scope.

valuereifyWithLocals_maybe :: DsMonad q => Name -> q (Maybe Info)
#

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.

valuemkDataNameWithLocals :: DsMonad q => String -> q Name
#

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.

valuemkTypeNameWithLocals :: DsMonad q => String -> q Name
#

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.

valuereifyNameSpace :: DsMonad q => Name -> q (Maybe NameSpace)
#

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, mkName "==", where == 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.

classclass (Quasi m, MonadFail m) => DsMonad (m :: Type -> Type) where
#

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

Methods

Instances7DsMonad, …
newtypenewtype DsM (q :: Type -> Type) a
#

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

Instances8MonadTrans, Monad, Functor, MonadFail, Applicative, MonadIO, …
  • MonadTrans DsMDefined in th-desugar-1.17 · Language.Haskell.TH.Desugar.Reify
  • Monad q => Monad (DsM q)Defined in th-desugar-1.17 · Language.Haskell.TH.Desugar.Reify
  • Functor q => Functor (DsM q)Defined in th-desugar-1.17 · Language.Haskell.TH.Desugar.Reify
  • MonadFail q => MonadFail (DsM q)Defined in th-desugar-1.17 · Language.Haskell.TH.Desugar.Reify
  • Applicative q => Applicative (DsM q)Defined in th-desugar-1.17 · Language.Haskell.TH.Desugar.Reify
  • MonadIO q => MonadIO (DsM q)Defined in th-desugar-1.17 · Language.Haskell.TH.Desugar.Reify
  • Quasi q => Quasi (DsM q)Defined in th-desugar-1.17 · Language.Haskell.TH.Desugar.Reify
  • (Quasi q, MonadFail q) => DsMonad (DsM q)Defined in th-desugar-1.17 · Language.Haskell.TH.Desugar.Reify

Nested pattern flattening

2 declarations
valuescExp :: DsMonad q => DExp -> q DExp
#

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.

Capture-avoiding substitution and utilities

0 declarations

Free variable calculation

2 declarations

Extract the term variables bound by a DPat.

This does not extract any type variables bound by pattern signatures, constructor patterns, or type patterns.

Utility functions

29 declarations
valueflattenDValD :: Quasi q => DLetDec -> q [DLetDec]
#

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.

valuegetRecordSelectors :: DsMonad q => [DCon] -> q [DLetDec]
#

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

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 [DConP X1 [DVarP field]] (DVarE field)
          , DClause [DConP X2 [DVarP field]] (DVarE field) ] ]

instead of returning one binding for X1 and another binding for X2.

getRecordSelectors does not attempt to filter out "naughty" record selectors—that is, records whose field types mention existentially quantified type variables that do not appear in the constructor's return type. Here is an example of a naughty record selector:

data Some :: (Type -> Type) -> Type where
  MkSome :: { getSome :: f a } -> Some f

GHC itself will not allow the use of getSome as a top-level function due to its type f a mentioning the existential variable a, but getRecordSelectors will return it nonetheless. Ultimately, this design choice is a practical one, as detecting which type variables are existential in Template Haskell is difficult in the general case.

valuemkTypeName :: Quasi q => String -> q Name
#

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

valuemkDataName :: Quasi q => String -> q Name
#

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

valuenewUniqueName :: Quasi q => String -> q Name
#

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

valuemaybeDCaseE :: MatchContext -> DExp -> [DMatch] -> DExp
#

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

Extract the degree of a tuple Name.

In addition to recognizing tuple syntax (e.g., ''(,,)), this also recognizes the following:

  • ''Unit (for 0-tuples)

  • ''Solo/'MkSolo (for 1-tuples)

  • ''TupleN (for N-tuples)

In recent versions of GHC, ''() is a synonym for ''Unit, ''(,) is a synonym for ''Tuple2, and so on. As a result, we must check for ''Unit and ''TupleN in tupleDegree_maybe to be thorough. (There is no special tuple syntax for ''Solo/'MkSolo, but we check them here as well for the sake of completeness.)

Extract the degree of an unboxed sum Name.

In addition to recognizing unboxed sum syntax (e.g., ''()), this also recognizes ''SumN# (for unboxed N-ary sum type constructors). In recent versions of GHC, ''Sum2# is a synonym for ''(), ''Sum3# is a synonym for ''(), and so on. As a result, we must check for ''SumN# in unboxedSumNameDegree_maybe to be thorough.

Extract the degree of an unboxed tuple Name.

In addition to recognizing unboxed tuple syntax (e.g., ''()), this also recognizes the following:

  • ''Unit# (for unboxed 0-tuples)

  • ''Solo#/'Solo# (for unboxed 1-tuples)

  • ''TupleN# (for unboxed N-tuples)

In recent versions of GHC, ''(##) is a synonym for ''Unit#, ''() is a synonym for ''Tuple2#, and so on. As a result, we must check for ''Unit#, and ''TupleN in unboxedTupleNameDegree_maybe to be thorough. (There is no special unboxed tuple type constructor for ''Solo#/'Solo#, but we check them here as well for the sake of completeness.)

valuebindIP :: a -> (IP name a => r) -> r
#

Get an implicit param constraint (IP name a, which is the desugared form of (?name :: a)) from an explicit value.

This function is only available with GHC 8.0 or later.

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.

Take a list of DTypes, find their free variables, and sort them in reverse topological order to ensure that they are well scoped. In other words, the free variables are ordered such that:

  1. Whenever an explicit kind signature of the form (A :: K) is encountered, the free variables of K will always appear to the left of the free variables of A in the returned result.

  2. The constraint in (1) notwithstanding, free variables will appear in left-to-right order of their original appearance.

On older GHCs, this takes measures to avoid returning explicitly bound kind variables, which was not possible before TypeInType.

Take a telescope of DTyVarBndrs, find the free variables in their kinds, and sort them in reverse topological order to ensure that they are well scoped. Because the argument list is assumed to be telescoping, kind variables that are bound earlier in the list are not returned. For example, this:

toposortKindVarsOfTvbs [a :: k, b :: Proxy a]

Will return [k], not [k, a], since a is bound earlier by a :: k.

FunArgs and VisFunArg

datadata FunArgs
#

The list of arguments in a function Type.

Constructors

Instances3Eq, Data, Show
  • Eq FunArgsDefined in th-desugar-1.17 · Language.Haskell.TH.Desugar.Util
  • Data FunArgsDefined in th-desugar-1.17 · Language.Haskell.TH.Desugar.Util
  • Show FunArgsDefined in th-desugar-1.17 · Language.Haskell.TH.Desugar.Util
datadata ForallTelescope
#

The type variable binders in a forall. This is not used by the TH AST itself, but this is used as an intermediate data type in FAForalls.

Constructors

Instances3Eq, Data, Show
datadata VisFunArg
#

A visible function argument type (i.e., one that must be supplied explicitly in the source code). This is in contrast to invisible arguments (e.g., the c in c => r), which are instantiated without the need for explicit user input.

Constructors

Instances3Eq, Data, Show
  • Eq VisFunArgDefined in th-desugar-1.17 · Language.Haskell.TH.Desugar.Util
  • Data VisFunArgDefined in th-desugar-1.17 · Language.Haskell.TH.Desugar.Util
  • Show VisFunArgDefined in th-desugar-1.17 · Language.Haskell.TH.Desugar.Util

DFunArgs and DVisFunArg

datadata DFunArgs
#

The list of arguments in a function DType.

Constructors

Instances5Eq, Data, Show, Generic, Rep
datadata DVisFunArg
#

A visible function argument type (i.e., one that must be supplied explicitly in the source code). This is in contrast to invisible arguments (e.g., the c in c => r), which are instantiated without the need for explicit user input.

Constructors

Instances5Eq, Data, Show, Generic, Rep

TypeArg

datadata TypeArg
#

An argument to a type, either a normal type (TANormal) or a visible kind application (TyArg).

TypeArg is useful when decomposing an application of a Type to its arguments (e.g., in unfoldType).

Constructors

Instances4Eq, Data, Show, Desugar
  • Eq TypeArgDefined in th-desugar-1.17 · Language.Haskell.TH.Desugar.Util
  • Data TypeArgDefined in th-desugar-1.17 · Language.Haskell.TH.Desugar.Util
  • Show TypeArgDefined in th-desugar-1.17 · Language.Haskell.TH.Desugar.Util
  • Desugar TypeArg DTypeArgDefined in th-desugar-1.17 · Language.Haskell.TH.Desugar
valueunfoldType :: Type -> (Type, [TypeArg])
#

Decompose an applied type into its individual components. For example, this:

Proxy @Type Char

would be unfolded to this:

(ConT ''Proxy, [TyArg (ConT ''Type), TANormal (ConT ''Char)])

This process forgets about infix application, so both of these types:

Int :++: Int
(:++:) Int Int

will be unfolded to this:

(ConT ''(:+:), [TANormal (ConT ''Int), TANormal (ConT ''Int)])

This function should only be used after all UInfixT and PromotedUInfixT types have been resolved (e.g., via th-abstraction's resolveInfixT function).

DTypeArg

datadata DTypeArg
#

An argument to a type, either a normal type (DTANormal) or a visible kind application (DTyArg).

DTypeArg does not appear directly in the th-desugar AST, but it is useful when decomposing an application of a DType to its arguments.

Instances6Eq, Data, Show, Generic, Desugar, Rep

Extracting bound names

Extract the names bound in a Stmt.

This does not extract any type variables bound by pattern signatures, constructor patterns, or type patterns.

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

This does not extract any type variables bound by pattern signatures, constructor patterns, or type patterns.

Extract the names bound in a Pat.

This does not extract any type variables bound by pattern signatures, constructor patterns, or type patterns.