th-desugar
Functions to desugar Template Haskell
https://github.com/goldfirere/th-desugar
| LTS Haskell 24.17: | 1.17 | 
| Stackage Nightly 2025-10-31: | 1.18 | 
| Latest on Hackage: | 1.18 | 
th-desugar-1.18@sha256:872c907679a711f6429a0d14203c5a487db847485e1e371544604ae1d2db8164,3924Module documentation for 1.18
- Language- Language.Haskell- Language.Haskell.TH
 
 
- Language.Haskell
th-desugar Package
This package provides the Language.Haskell.TH.Desugar module, which desugars
Template Haskell’s rich encoding of Haskell syntax into a simpler encoding.
This desugaring discards surface syntax information (such as the use of infix
operators) but retains the original meaning of the TH code. The intended use
of this package is as a preprocessor for more advanced code manipulation
tools. Note that the input to any of the ds... functions should be produced
from a TH quote, using the syntax [| ... |]. If the input to these functions
is a hand-coded TH syntax tree, the results may be unpredictable. In
particular, it is likely that promoted datatypes will not work as expected.
One explicit goal of this package is to reduce the burden of supporting multiple GHC / TH versions. Thus, the desugared language is the same across all GHC versions, and any inconsistencies are handled internally.
The package was designed for use with the singletons package, so some design
decisions are based on that use case, when more than one design choice was
possible.
I will try to keep this package up-to-date with respect to changes in GHC. The minimum supported version of GHC is 8.0, which was chosen to avoid various Template Haskell bugs in older GHC versions that affect how this library desugars code. If this choice negatively impacts you, please submit a bug report.
Known limitations
Desugaring depends on language extensions of use sites
Suppose you quote some Template Haskell declarations in module A:
{-# LANGUAGE ... #-}
module A where
decs :: Q [Dec]
decs = [d| ... |]
And later desugar the declarations with th-desugar in module B:
{-# LANGUAGE ... #-}
module B where
import A (decs)
import Language.Haskell.TH.Desugar (dsDecs)
$(do desugaredDecs <- dsDecs decs
     ...)
There are some situations where th-desugar’s desugaring depends on which
language extensions are enabled, such as:
- MonadFailDesugaring(for desugaring partial pattern matches in- donotation)
- NoFieldSelectors(for determining if a record field can be reified as a field selector with- lookupValueNameWithLocals)
Somewhat counterintuitively, th-desugar will consult the language extensions
in module B (the site where the decs are used) for this process, not module
A (where the decs were defined). This is really a Template Haskell
limitation, since Template Haskell does not offer any way to reify which
language extensions were enabled at the time the declarations were defined. As a
result, th-desugar can only check for language extensions at use sites.
Limited support for kind inference
th-desugar sometimes has to construct types for certain Haskell entities.
For instance, th-desugar desugars all Haskell98-style constructors to use
GADT syntax, so the following:
data T (a :: k) = MkT (Proxy a)
Will be desugared to something like this:
data T (a :: k) where
  MkT :: forall k (a :: k). Proxy a -> T (a :: k)
Notice that k is explicitly quantified in the type of MkT. This is due to
an additional pass that th-desugar performs over the type variable binders
of T to extract all implicitly quantified variables and make them explicit.
This makes the desugared types forwards-compatible with a
future version of GHC
that requires all kind variables in a top-level forall to be explicitly
quantified.
This process of extracting all implicitly quantified kind variables is not
perfect, however. There are some obscure programs that will cause th-desugar
to produce type variable binders that are ill scoped. Here is one example:
data P k (a :: k)
data Foo (a :: Proxy j) (b :: k) c = MkFoo c (P k j)
If you squint hard at MkFoo, you’ll notice that j :: k. However, this
relationship is not expressed syntactically, which means that th-desugar
will not be aware of it. Therefore, th-desugar will desugar Foo to:
data Foo (a :: Proxy j) (b :: k) c where
  MkFoo :: forall j k (a :: Proxy j) (b :: k) c.
           c -> P k j -> Foo (a :: Proxy j) (b :: k) c
This is incorrect since k must come before j in order to be well scoped.
There is a workaround to this issue, however: add more explicit kind
information. If you had instead written this:
data Foo (a :: Proxy (j :: k)) (b :: k) c = MkFoo c (P k j)
Then the fact that j :: k is expressed directly in the AST, so th-desugar
is able to pick up on it and pick forall k j (a :: Proxy j) (b :: k) c. <...>
as the telescope for the type of MkFoo.
The following constructs are known to be susceptible to this issue:
- Desugared Haskell98-style constructors
- Locally reified class methods
- Locally reified record selectors
- Locally reified data constructors
- Locally reified type family instances (on GHC 8.8 and later, in which the
Template Haskell AST supports explicit forallsin type family equations)
Limited support for linear types
Currently, the th-desugar AST deliberately makes it impossible to represent
linear types, and desugaring a linear function arrow will simply turn into a
normal function arrow (->). This choice is partly motivated by issues in the
way that linear types interact with Template Haskell, which sometimes make it
impossible to tell whether a reified function type is linear or not. See, for
instance, GHC#18378.
Limitations of support for desugaring guards
th-desugar supports guards in the sense that it will desugar guards to
equivalent code that instead uses case expressions. For example, this code:
f (x, y)
  | x == "hello" = x
  | otherwise = y
Will be desugared to this code:
f arg =
  case arg of
    (x, y) ->
      case x2 == "hello" of
        True  -> x
        False -> y
This has the advantage that it saves users from needing to care about the complexities of guards. It does have some drawbacks, however, which we describe below.
Desugaring guards can result in quadratic code size
If you desugar this program involving guards:
data T = A Int | B Int | C Int
f :: T -> T -> Maybe Int
f (A x1) (A x2)
  | x1 == x2
  = Just x1
f (B x1) (B x2)
  | x1 == x2
  = Just x1
f (C x1) (C x2)
  | x1 == x2
  = Just x1
f _ _ = Nothing
You will end up with:
f :: T -> T -> Maybe Int
f arg1 arg2 =
  case (# arg1, arg2 #) of
    (# A x1, A x2 #) ->
      case x1 == x2 of
        True ->
          Just x1
        False ->
          case (# arg1, arg2 #) of
            (# B y1, B y2 #) ->
              case y1 == y2 of
                True ->
                  Just y1
                False ->
                  case (# arg1, arg2 #) of
                    (# C z1, C z2 #) ->
                      case z1 == z2 of
                        True ->
                          Just z1
                        False ->
                          case (# arg1, arg2 #) of
                            (# _, _ #) ->
                              Nothing
                    (# _, _ #) ->
                      Nothing
            (# C y1, C y2 #) ->
              case y1 == y2 of
                True ->
                  Just y1
                False ->
                  case (# arg1, arg2 #) of
                    (# _, _ #) ->
                      Nothing
            (# _, _ #) ->
              Nothing
    (# B x1, B x2 #) ->
      case x1 == x2 of
        True ->
          Just x1
        False ->
          case (# arg1, arg2 #) of
            (# C y1, C y2 #) ->
              case y1 == y2 of
                True ->
                  Just y1
                False ->
                  case (# arg1, arg2 #) of
                    (# _, _ #) ->
                      Nothing
            (# _, _ #) ->
              Nothing
    (# C x1, C x2 #) ->
      case x1 == x2 of
        True ->
          Just x1
        False ->
          case (# arg1, arg2 #) of
            (# _, _ #) ->
              Nothing
    (# _, _ #) ->
      Nothing
That is signficantly more code. In the worst case, the algorithm that
th-desugar uses for desugaring guards can lead to a quadratic increase in
code size. One way to avoid this is avoid having incomplete guards that fall
through to later clauses. That is, if you rewrite the original code to this:
f :: T -> T -> Maybe Int
f (A x1) (A x2)
  | x1 == x2
  = Just x1
  | otherwise
  = Nothing
f (B x1) (B x2)
  | x1 == x2
  = Just x1
  | otherwise
  = Nothing
f (C x1) (C x2)
  | x1 == x2
  = Just x1
  | otherwise
  = Nothing
Then th-desugar will desugar it to:
f :: T -> T -> Maybe Int
f arg1 arg2 =
  case (# arg1, arg2 #) of
    (# A x1, A x2 #) ->
      case x1 == x2 of
        True ->
          Just x1
        False ->
          Nothing
    (# B x1, B x2 #) ->
      case x1 == x2 of
        True ->
          Just x1
        False ->
          Nothing
    (# C x1, C x2 #) ->
      case x1 == x2 of
        True ->
          Just x1
        False ->
          Nothing
This code, while still more verbose than the original, uses a constant amount of extra code per clause.
Desugaring guards can produce more warnings than the original code
The approach that th-desugar uses to desugar guards can result in code that
produces GHC compiler warnings (if -fenable-th-splice-warnings is enabled)
where the original code does not. For example, consider the example from above:
data T = A Int | B Int | C Int
f :: T -> T -> Maybe Int
f (A x1) (A x2)
  | x1 == x2
  = Just x1
f (B x1) (B x2)
  | x1 == x2
  = Just x1
f (C x1) (C x2)
  | x1 == x2
  = Just x1
f _ _ = Nothing
This code compiles without any GHC warnings. If you desugar this code using
th-desugar, however, it will produce these warnings:
warning: [-Woverlapping-patterns]
    Pattern match is redundant
    In a case alternative: (# B y1, B y2 #) -> ...
   |
   |             (# B y1, B y2 #) ->
   |             ^^^^^^^^^^^^^^^^^^^...
warning: [-Woverlapping-patterns]
    Pattern match is redundant
    In a case alternative: (# C y1, C y2 #) -> ...
   |
   |             (# C y1, C y2 #) ->
   |             ^^^^^^^^^^^^^^^^^^^...
warning: [-Woverlapping-patterns]
    Pattern match is redundant
    In a case alternative: (# C y1, C y2 #) -> ...
   |
   |             (# C y1, C y2 #) ->
   |             ^^^^^^^^^^^^^^^^^^^...
GHC is correct here: these matches are wholly redundant. th-desugar could
potentially recognize this and perform a more sophisticated analysis to detect
and remove such matches when desugaring guards, but it currently doesn’t do
such an analysis.
No support for view patterns
th-desugar does not support desugaring view patterns. An alternative to using
view patterns in the patterns of a function is to use pattern guards.
Currently, there is not a viable workaround for using view patterns in pattern
synonym definitions—see this th-desugar
issue.
No support for or-patterns
th-desugar does not support desugaring
or-patterns.
See this th-desugar
issue.
No support for ApplicativeDo
th-desugar does not take the ApplicativeDo extension into account when
desugaring do notation. For example, if you desugar this:
{-# LANGUAGE ApplicativeDo #-}
f x y = do
  x' <- x
  y' <- y
  return (x' ++ y')
Then th-desugar will translate the uses of <- in the do block to uses of
Monad operations (e.g., (>>=)) rather than Applicative operations (e.g.,
(<*>)). See this th-desugar
issue.
No support for RecursiveDo
th-desugar does not support the RecursiveDo extension at all, so it cannot
desugar any uses of mdo expressions or rec statements.
No support for unresolved infix operators
th-desugar does not support desugaring unresolved infix operators, such as
UInfixE. You are unlikely to encounter this limitation when dealing with
Template Haskell quotes, since quoted infix operators will translate to uses of
InfixE rather than UInfixE. Rather, this limitation would only be
encountered if you manually construct a Template Haskell Exp using UInfixE.
Changes
th-desugar release notes
Version 1.18 [2024.12.11]
- 
Support GHC 9.12. 
- 
Add further support for embedded types in terms. The DExptype now has aDForallEdata constructor (mirroringForallEandForallVisEintemplate-haskell) and aDConstrainedEdata constructor (mirroringConstrainedEintemplate-haskell).
- 
The DLamEandDCaseEdata constructors (as well as the relatedmkDLamEFromDPatsfunction) are now deprecated in favor of the newDLamCasesEdata constructor.DLamE,DCaseE, andmkDLamEFromDPatswill be removed in a future release ofth-desugar, so users are encouraged to migrate. For more details on how to migrate your code, see this document.
- 
The type of the dsMatchesfunction has changed:-dsMatches :: DsMonad q => Name -> [Match] -> q [DMatch] +dsMatches :: DsMonad q => MatchContext -> [Match] -> q [DMatch]In particular: - dsMatchesfunction no longer includes a- Nameargument for the variable being scrutinized, as the new approach that- th-desugaruses to desugar- Matches no longer requires this.
- dsMatchesnow requires a- MatchContextargument, which determines what kind of “- Non-exhaustive patterns in ...” error it raises when reaching a fallthrough case for non-exhaustive matches.
 
- 
Add a maybeDCasesE :: MatchContext -> [DExp] -> [DClause] -> DExpfunction.maybeDCasesEis similar tomaybeDCaseEexcept that it matches on multiple expressions (using\\cases) instead of matching on a single expression.
- 
Add support for desugaring higher-order uses of embedded type patterns (e.g., \(type a) (x :: a) -> x :: a) and invisible type patterns (e.g.,\ @a (x :: a) -> x :: a).
- 
Add a Quoteinstance forDsM.
- 
Add mapDTVNameandmapDTVKindfunctions, which allow mapping over theNameandDKindof aDTyVarBndr, respectively.
- 
Export substTyVarBndrfromLanguage.Haskell.TH.Desugar.Subst.
- 
Add a Language.Haskell.TH.Desugar.Subst.Capturingmodule. This exposes mostly the same API asLanguage.Haskell.TH.Desugar.Subst, except that the substitution functions inLanguage.Haskell.TH.Desugar.Subst.Capturingdo not avoid capture when subtituting into a @forall@ type. As a result, these substitution functions are pure rather than monadic.
- 
Add dMatchUpSAKWithDecl, a function that matches up type variable binders from a standalone kind signature to the corresponding type variable binders in the type-level declaration’s header:- The type signature for dMatchUpSAKWithDeclreturns[DTyVarBndr ForAllTyFlag], whereForAllTyFlagis a new data type that generalizes bothSpecificityandBndrVis.
- Add dtvbForAllTyFlagsToSpecsanddtvbForAllTyFlagsToBndrVisfunctions, which allow converting the results of callingdMatchUpSAKWithDeclto[DTyVarBndrSpec]or[DTyVarBndrVis], respectively.
- Also add matchUpSAKWithDecl,tvbForAllTyFlagsToSpecs, andtvbForAllTyFlagsToBndrVisfunctions, which work overTyVarBndrinstead ofDTyVarBndr.
 
- The type signature for 
- 
Locally reifying the type of a data constructor or class method now yields type signatures with more precise type variable information, as th-desugarnow incorporates information from the standalone kind signature (if any) for the parent data type or class, respectively. For instance, consider the following data type declaration:type P :: forall {k}. k -> Type data P (a :: k) = MkPIn previous versions of th-desugar, locally reifyingMkPwould yield the following type:MkP :: forall k (a :: k). P aThis was subtly wrong, as kis marked as specified (i.e., eligible for visible type application), not inferred. Inth-desugar-1.18, however, the locally reified type will markkas inferred, as expected:MkP :: forall {k} (a :: k). P aSimilarly, desugaring MkPfrom Template Haskell toth-desugarresults in a data constructor with the expected type above.- 
As a result of these changes, the type of dsConhas changed slightly:-dsCon :: DsMonad q => [DTyVarBndrUnit] -> DType -> Con -> q [DCon] +dsCon :: DsMonad q => [DTyVarBndrSpec] -> DType -> Con -> q [DCon]
 
- 
Version 1.17 [2024.05.12]
- Support GHC 9.10.
- Add support namespace identifiers in fixity declarations. As part of these
changes, the DInfixDdata constructor now has aNamespaceSpecifierfield.
- Add support for SCCdeclarations via the newDSCCPdata constructor for theDPragmadata type.
- Add partial support for embedded types in expressions (via the new DTypeEdata constructor) and in patterns (via the newDTypePdata constructor). This is only partial support because the use ofDTypePis supported in the clauses of function declarations, but not in lambda expressions,\caseexpressions, or\casesexpressions. See the “Known limitations” section of theth-desugarREADMEfor full details.
- Add partial support for invisible type patterns via the new DInvisPdata constructor. Just like withDTypeP,th-desugaronly supports the use ofDInvisPin the clauses of function declarations. See the “Known limitations” section of theth-desugarREADMEfor full details.
- extractBoundNamesDPatno longer extracts type variables from constructor patterns. That this function ever did extract type variables was a mistake, and the new behavior of- extractBoundNamesDPatbrings it in line with the behavior- extractBoundNamesPat.
- The unboxedTupleNameDegree_maybefunction now returns:- Just 0when the argument is- ''Unit#
- Just 1when the argument is- ''Solo#
- Just <N>when the argument is- ''Tuple<N>#This is primarily motivated by the fact that with GHC 9.10 or later,- ''(##)is syntactic sugar for- ''Unit#,- ''(#,#)is syntactic sugar for- Tuple2#, and so on.
 
- The unboxedSumNameDegree_maybefunction now returnsJust nwhen the argument isSum<N>#. This is primarily motivated by the fact that with GHC 9.10 or later,''(#|#)is syntactic sugar forSum2#,''(#||#)is syntactic sugar forSum3#, and so on.
- Add FoldableandTraversableinstances forDTyVarBndrSpec.
Version 1.16 [2023.10.13]
- 
Support GHC 9.8. 
- 
Require th-abstraction-0.6or later.
- 
Add support for invisible binders in type-level declarations. As part of this change: - Language.Haskell.TH.Desugarnow exports a- DTyVarBndrVistype synonym, which is the- th-desugarcounterpart to- TyVarBndrVis. It also exports a- dsTvbVisfunction, which is the- DTyVarBndrViscounterpart to- dsTvbSpecand- dsTvbUnit.
- Language.Haskell.TH.Desugarnow re-exports- BndrVisfrom- template-haskell.
- The DDataD,DTySynD,DClassD,DDataFamilyD, andDTypeFamilyHeadparts of theth-desugarAST now useDTyVarBndrVisinstead ofDTyVarBndrUnit.
- The mkExtraDKindBinders,dsCon, anddsDataDecfunctions now useDTyVarBndrVisinstead ofDTyVarBndrUnit.
- The getDataDfunction now usesTyVarBndrVisinstead ofTyVarBndrUnit.
 It is possible that you will need to convert between TyVarBndrUnitandTyVarBndrVisto adapt your existingth-desugarcode. (Note thatTyVarBndr flagis an instance ofFunctor, so this can be accomplished withfmap.)
- 
Language.Haskell.TH.Desugarnow exports a family of functions for converting type variable binders into type arguments while preserving their visibility:- The tyVarBndrVisToTypeArgandtyVarBndrVisToTypeArgWithSigfunctions convert aTyVarBndrVisto aTypeArg.tyVarBndrVisToTypeArgomits kind signatures when convertingKindedTVs, whiletyVarBndrVisToTypeArgWithSigpreserves kind signatures.
- The dTyVarBndrVisToDTypeArganddTyVarBndrVisToDTypeArgWithSigfunctions convert aDTyVarBndrVisto aDTypeArg.dTyVarBndrVisToDTypeArgomits kind signatures when convertingDKindedTVs, whiledTyVarBndrVisToDTypeArgWithSigpreserves kind signatures.
 
- The 
- 
th-desugarnow supports generating typed Template Haskell quotes and splices via the newDTypedBracketEandDTypedSpliceEconstructors ofDExp, respectively.
- 
The lookupValueNameWithLocalsfunction will no longer reify field selectors when theNoFieldSelectorslanguage extension is set, mirroring the behavior of thelookupValueNamefunction intemplate-haskell. Note that this will only happen when using GHC 9.8 or later, as previous versions of GHC do not equip Template Haskell with enough information to conclude whether a value is a record field or not.
- 
The tupleNameDegree_maybefunction now returns:- Just 0when the argument is- ''Unit
- Just 1when the argument is- ''Soloor- 'MkSolo
- Just <N>when the argument is- ''Tuple<N>This is primarily motivated by the fact that with GHC 9.8 or later,- ''()is syntactic sugar for- ''Unit,- ''(,)is syntactic sugar for- Tuple2, and so on. We also include cases for- ''Soloand- 'MkSolofor the sake of completeness, even though they do not have any special syntactic sugar.
 
- 
The tupleDegree_maybe,unboxedSumDegree_maybe, andunboxedTupleDegree_maybefunctions have been removed. Their only use sites were in thetupleNameDegree_maybe,unboxedSumNameDegree_maybe, andunboxedTupleNameDegree_maybefunctions, respectively. Moreover,tupleDegree_maybe’s semantics were questionable, considering that it could potentially returnJust <N>for a custom data type namedTuple<N>, even if the custom data type has no relation to theTuple<N>types defined inGHC.Tuple.
- 
The matchTyfunction now looks through visible kind applications (i.e.,DAppKindTs) wheneverYesIgnoreKindsis given.
- 
Fix a bug in which infix data family declaration would mistakenly be rejected when reified locally. 
- 
Fix a bug in which data types that use visible dependent quantification would produce ill-scoped code when desugared. 
Version 1.15 [2023.03.12]
- 
Support GHC 9.6. 
- 
The NewOrDatadata type has been renamed toDataFlavorand extended to supporttype datadeclarations:-data NewOrData = NewType | Data +data DataFlavor = NewType | Data | TypeDataDesugaring upholds the following properties regarding TypeData:- A DDataDwith aDataFlavorofTypeDatacannot have any deriving clauses or datatype contexts, and theDConFieldsin eachDConwill be aNormalCwhere eachBangis equal toBang NoSourceUnpackedness NoSourceStrictness.
- A DDataInstDcan have aDataFlavorofNewTypeorData, but notTypeData.
 
- A 
- 
The type of getDataDhas been changed to also include aDataFlavor:-getDataD :: DsMonad q => String -> Name -> q ([TyVarBndrUnit], [Con]) +getDataD :: DsMonad q => String -> Name -> q (DataFlavor, [TyVarBndrUnit], [Con])
- 
Local reification can now reify the types of pattern synonym record selectors. 
- 
Fix a bug in which the types of locally reified GADT record selectors would sometimes have type variables quantified in the wrong order. 
Version 1.14 [2022.08.23]
- Support GHC 9.4.
- Drop support for GHC 7.8 and 7.10. As a consequence of this, the
strictToBangfunction was removed as it no longer serves a useful purpose.
- Desugared lambda expressions and guards that bind multiple patterns can now
have patterns with unlifted types. The desugared code uses UnboxedTuplesto make this possible, so if you load the desugared code into GHCi on prior to GHC 9.2, you will need to enable-fobject-code.
- th-desugarnow desugars- PromotedInfixTand- PromotedUInfixT, which were added in GHC 9.4. Mirroring the existing treatment of other- Promoted*- Types,- PromotedInfixTis desugared to an application of a- DConTapplied to two arguments, just like- InfixTis desugared. Similarly, attempting to desugar a- PromotedUInfixTresults in an error, just like attempting to desugar a- UInfixTwould be.
- th-desugarnow supports- DefaultD(i.e.,- defaultdeclarations) and- OpaqueP(i.e.,- OPAQUEpragmas), which were added in GHC 9.4.
- th-desugarnow desugars- LamCasesE(i.e.,- \casesexpressions), which was added in GHC 9.4. A- \casesexpression is desugared to an ordinary lambda expression, much like- \caseis currently desugared.
- Fix an inconsistency which caused non-exhaustive caseexpressions to be desugared into uses ofEmptyCase. Non-exhaustivecaseexpressions are now desugared into code that throws a “Non-exhaustive patterns in...” error at runtime, just as all other forms of non-exhaustive expressions are desugared.
- Fix a bug in which expandTypewould not expand closed type families when applied to arguments containing type variables.
Version 1.13.1 [2022.05.20]
- Allow building with mtl-2.3.*.
Version 1.13 [2021.10.30]
- 
Support GHC 9.2. 
- 
Add support for visible type application in data constructor patterns. As a result of these changes, the DConPconstructor now has an extra field to represent type arguments:data DPat = ... - | DConP Name [DPat] -- fun (Just x) = ... + | DConP Name [DType] [DPat] -- fun (Just @t x) = ... | ...
- 
Add support for the e.fieldand(.field)syntax from theOverloadedRecordDotlanguage extension.
- 
The Maybe [DTyVarBndrUnit]fields inDInstanceDandDStandaloneDerivDare no longer used when sweetening. Previously,th-desugarwould attempt to sweeten theseDTyVarBndrUnits by turning them into a nestedForallT, but GHC 9.2 or later no longer allow this, as they forbid nestedforalls in instance heads entirely. As a result, theMaybe [DTyVarBndrUnit]fields are now only useful for functions that consumeDDecs directly.
- 
Fix a bug in which desugared GADT constructors would sometimes incorrectly claim that they were declared infix, despite this not being the case. 
Version 1.12 [2021.03.12]
- 
Support GHC 9.0. 
- 
Add support for explicit specificity. As part of this change, the way th-desugarrepresents type variable binders has been overhauled:- 
The DTyVarBndrdata type is now parameterized by aflagtype parameter:data DTyVarBndr flag = DPlainTV Name flag | DKindedTV Name flag DKindThis can be instantiated to Specificity(for type variable binders that can be specified or inferred) or()(for type variable binders where specificity is irrelevant).DTyVarBndrSpecandDTyVarBndrUnitare also provided as type synonyms forDTyVarBndr SpecificityandDTyVarBndr (), respectively.
- 
In order to interface with TyVarBndr(the TH counterpart toDTyVarBndr) in a backwards-compatible way,th-desugarnow depends on theth-abstractionlibrary.
- 
The ForallVisFlaghas been removed in favor of the newDForallTelescopedata type, which not only distinguishes between invisible and visibleforalls but also uses the correct type variable flag for invisible type variables (Specificity) and visible type variables (()).
- 
The type of the dsTvbis now different on pre-9.0 versions of GHC:#if __GLASGOW_HASKELL__ >= 900 dsTvb :: DsMonad q => TyVarBndr flag -> q (DTyVarBndr flag) #else dsTvb :: DsMonad q => flag -> TyVarBndr -> q (DTyVarBndr flag) #endifThis is unfortunately required by the fact that prior to GHC 9.0, there is no flaginformation stored anywhere in aTyVarBndr. If you need to usedsTvbin a backward-compatible way,L.H.TH.Desugarnow providesdsTvbSpecanddsTvbUnitfunctions which specialisedsTvbto particularflagtypes:dsTvbSpec :: DsMonad q => TyVarBndrSpec -> q DTyVarBndrSpec dsTvbUnit :: DsMonad q => TyVarBndrUnit -> q DTyVarBndrUnit
 
- 
- 
The type of the getRecordSelectorsfunction has changed:-getRecordSelectors :: DsMonad q => DType -> [DCon] -> q [DLetDec] +getRecordSelectors :: DsMonad q => [DCon] -> q [DLetDec]The old type signature had a DTypeargument whose sole purpose was to help determine which type variables were existential, as this information was used to filter out “naughty” record selectors, like the example below:data Some :: (Type -> Type) -> Type where MkSome :: { getSome :: f a } -> Some fThe old implementation of getRecordSelectorswould not includegetSomein the returned list, as its typef amentions an existential type variable,a, that is not mentioned in the return typeSome f. The new implementation ofgetRecordSelectors, on the other hand, makes no attempt to filter out naughty record selectors, so it would includegetSome.This reason for this change is ultimately because determining which type variables are existentially quantified in the context of Template Haskell is rather challenging in the general case. There are heuristics we could employ to guess which variables are existential, but we have found these heuristics difficult to predict (let alone specify). As a result, we take the slightly less correct (but much easier to explain) approach of returning all record selectors, regardless of whether they are naughty or not. 
- 
The conExistentialTvbsfunction has been removed. It was horribly buggy, especially in the presence of GADT constructors. Moreover, this function was used in the implementation ofgetRecordSelectorsfunction, so bugs inconExistentialTvbsoften affected the results ofgetRecordSelectors.
- 
The types of decToTH,letDecToTH, andpragmaToTHhave changed:-decToTH :: DDec -> [Dec] +decToTH :: DDec -> Dec -letDecToTH :: DLetDec -> Maybe Dec +letDecToTH :: DLetDec -> Dec -pragmaToTH :: DPragma -> Maybe Pragma +pragmaToTH :: DPragma -> PragmaThe semantics of pragmaToTHhave changed accordingly. Previously,pragmaToTHwould returnNothingwhen the argument is aDPragmathat is not supported on an old version of GHC, but now an error will be thrown instead.decToTHandletDecToTH, which transitively invokepragmaToTH, have had their types updated to accommodatepragmaToTH’s type change.
- 
The type of the substTyVarBndrsfunction has been simplified to avoid the needless use of continuation-passing style:-substTyVarBndrs :: Quasi q => DSubst -> [DTyVarBndr flag] -> (DSubst -> [DTyVarBndr flag] -> q a) -> q a +substTyVarBndrs :: Quasi q => DSubst -> [DTyVarBndr flag] -> q (DSubst, [DTyVarBndr flag])
- 
mkDLamEFromDPatshas now generates slightly more direct code for certain lambda expressions with@-patterns. For example,\x@y -> f x ywould previously desugar to\arg -> case arg of { y -> let x = y in f x y }, but it now desugars to\y -> let x = y in f x y.
- 
mkDLamEFromDPatsnow requires only aQuasicontext instead ofDsMonad.
Version 1.11 [2020.03.25]
- Support GHC 8.10.
- Add support for visible dependent quantification. As part of this change,
the way th-desugarrepresentsforalland constraint types has been overhauled:- 
The existing DForallTconstructor has been split into two smaller constructors:data DType = ... - | DForallT [DTyVarBndr] DCxt DType + | DForallT ForallVisFlag [DTyVarBndr] DType + | DConstrainedT DCxt DType | ... +data ForallVisFlag + = ForallVis + | ForallInvisThe previous design combined foralls and constraints into a single constructor, while the new design puts them in distinct constructorsDForallTandDConstrainedT, respectively. The newDForallTconstructor also has aForallVisFlagfield to distinguish invisibleforalls (e.g.,forall a. a) from visibleforalls (e.g.,forall a -> a).
- 
The unravelfunction has been renamed tounravelDTypeand now returns(DFunArgs, DType), whereDFunArgsis a data type that represents the possible arguments in a function type (see the Haddocks forDFunArgsfor more details). There is also anunravelDTypecounterpart forTypes namedunravelType, complete with its ownFunArgsdata type.{D}FunArgsalso have some supporting operations, includingfilter{D}VisFunArgs(to obtain only the visible arguments) andravel{D}Type(to construct a function type using{D}FunArgsand a return{D}Type).
 
- 
- Support standalone kind signatures by adding a DKiSigDconstructor toDDec.
- Add dsReifyType,reifyTypeWithLocals_maybe, andreifyTypeWithLocals, which allow looking up the types or kinds of locally declared entities.
- Fix a bug in which reifyFixityWithLocalswould not look into local fixity declarations inside of type classes.
- Fix a bug in which reifyFixityWithLocalswould return incorrect results for classes with associated type family defaults.
Version 1.10
- 
Support GHC 8.8. Drop support for GHC 7.6. 
- 
Add support for visible kind application, type variable forallsinRULES, and explicitforalls in type family instances. Correspondingly,- 
There is now a DAppKindTconstructor inDType.
- 
Previously, the DDataInstDconstructor had fields of typeNameand[DType]. Those have been scrapped in favor of a single field of typeDType, representing the application of the data family name (which was previously theName) to its arguments (which was previously the[DType]).DDataInstDalso has a new field of typeMaybe [DTyVarBndr]to represent its explicitly quantified type variables (if present).
- 
Previously, the DTySynEqnconstructor had a field of type[DType]. That has been scrapped in favor of a field of typeDType, representing the application of the type family name (whichDTySynEqndid not used to contain!) to its arguments (which was previously the[DType]).DTySynEqnalso has a new field of typeMaybe [DTyVarBndr]to represent its explicitly quantified type variables (if present).
- 
DTySynInstDno longer has a field of typeName, as that is redundant now that eachDTySynEqncontains the sameName.
- 
There is now a field of type Maybe [DTyVarBndr]in theDRulePconstructor to represent bound type variables inRULES(if present).
 
- 
- 
Add a field of type Maybe [DTyVarBndr]toDInstanceDandDStandaloneDerivDfor optionally quantifying type variables explicitly. If supplied with aJust, this sweetens the instance type to use aForallTto represent the explicit quantification. This trick is not supported forInstanceDon GHC 8.0 and forStandaloneDerivDon GHC 7.10 or 8.0, so be aware of this limitation if you supplyJustfor this field.
- 
Add support for desugaring implicit params. This does not involve any changes to the th-desugarAST, as:- (?x :: a) => ...is desugared to- IP "x" a => ....
- id ?xis desugared to- id (ip @"x").
- let ?x = 42 in ...is desugared to- let new_x_val = 42 in bindIP @"x" new_x_val ...(where- bindIPis a new utility function exported by- Language.Haskell.TH.Desugaron GHC 8.0 or later).
 In order to support this desugaring, the type signatures of dsLetDecanddsLetDecsnow return([DLetDec], DExp -> DExp)instead of just[DLetDec], whereDExp -> DExpis the expression which binds the values of implicit params (e.g.,\z -> bindIP @"x" new_x_val z) if any are bound. (If none are bound, this is simply theidfunction.)
- 
Fix a bug in which toposortTyVarsOfwould error at runtime if given types containingforalls as arguments.
- 
Fix a bug in which fvDTypewould return incorrect results if given a type containing quantified constraints.
- 
Fix a bug in which expandTypewould not expand type synonyms in the kinds of type variable binders inforalls.
- 
Fix a bug in which getRecordSelectorswould omit record selectors from GADT constructors.
- 
Fix a bug in which toposortTyVarsOfwould sometimes not preserve the left-to-right ordering ofNames generated withqNewName.
- 
Locally reified class methods, data constructors, and record selectors now quantify kind variables properly. 
- 
Desugared ADT constructors now quantify kind variables properly. 
- 
Remove DPred, as it has become too similar toDType. This also means that theDPatconstructors, which previously ended with the suffixPa, can now use the suffixP, mirroring TH.
- 
The type of applyDTypehas changed fromDType -> [DType] -> DTypetoDType -> [DTypeArg] -> DType, whereDTypeArgis a new data type that encodes whether an argument is a normal type argument (e.g., theIntinMaybe Int) or a visible kind argument (e.g., the@TypeinProxy @Type Char). ATypeArgdata type (which is likeDTypeArg, but withTypes/Kinds instead ofDTypes/DKinds) is also provided.A handful of utility functions for manipulating TypeArgs andDTypeArgs are also exported.
- 
th-desugarfunctions that compute free variables (e.g.,fvDType) now return anOSet, a variant ofSetthat remembers the order in which elements were inserted. A consequence of this change is that it fixes a bug that causes free variables to be computed in different orders depending on which unique numbers GHC happened to generate internally.
- 
Substition and type synonym expansion are now more efficient by avoiding the use of sybin inner loops.
Version 1.9
- 
Suppose GHC 8.6. 
- 
Add support for DerivingVia. Correspondingly, there is now aDDerivStrategydata type.
- 
Add support for QuantifiedConstraints. Correspondingly, there is now aDForallPrconstructor inDPredto represent quantified constraint types.
- 
Remove the DStarTconstructor ofDTypein favor ofDConT ''Type. Two utility functions have been added toLanguage.Haskell.TH.Desugarto ease this transition:- isTypeKindName: returns- Trueif the argument- Nameis that of- Typeor- ★(or- *, to support older GHCs).
- typeKindName: the name of- Type(on GHC 8.0 or later) or- *(on older GHCs).
 
- 
th-desugarnow desugars all data types to GADT syntax. The most significant API-facing changes resulting from this new design are:- 
The DDataD,DDataFamilyD, andDDataFamInstDconstructors ofDDecnow haveMaybe DKindfields that either haveJustan explicit return kind (e.g., thek -> Type -> Typeindata Foo :: k -> Type -> Type) orNothing(if lacking an explicit return kind).
- 
The DConconstructor previously had a field of typeMaybe DType, since there was a possibility it could be a GADT (with an explicit return type) or non-GADT (without an explicit return type) constructor. Since all data types are desugared to GADTs now, this field has been changed to be simply aDType.
- 
The type signature of dsConwas previously:dsCon :: DsMonad q => Con -> q [DCon]However, desugaring constructors now needs more information than before, since GADT constructors have richer type signatures. Accordingly, the type of dsConis now:dsCon :: 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]The instance Desugar [Con] [DCon]has also been removed, as the previous implementation ofdesugar(concatMapM dsCon) no longer has enough information to work.
 Some other utility functions have also been added as part of this change: - 
A conExistentialTvbsfunction has been introduced to determine the existentially quantified type variables of aDCon. Note that this function is not 100% accurate—refer to the documentation forconExistentialTvbsfor more information.
- 
A mkExtraDKindBindersfunction has been introduced to turn a data type’s return kind into explicit, fresh type variable binders.
- 
A toposortTyVarsOffunction, which finds the free variables of a list ofDTypes and returns them in a well scoped list that has been sorted in reverse topological order.
 
- 
- 
th-desugarnow desugars partial pattern matches indo-notation and list/monad comprehensions to the appropriate invocation offail. (Previously, these were incorrectly desugared intocaseexpressions with incomplete patterns.)
- 
Add a mkDLamEFromDPatsfunction for constructing aDLamEexpression using a list ofDPatarguments and aDExpbody.
- 
Add an unravelfunction for decomposing a function type into itsforall’d type variables, its context, its argument types, and its result type.
- 
Export a substTyVarBndrsfunction fromLanguage.Haskell.TH.Desugar.Subst, which substitutes over type variable binders in a capture-avoiding fashion.
- 
getDataD,dataConNameToDataName, anddataConNameToConfromLanguage.Haskell.TH.Desugar.Reifynow look up local declarations. As a result, the contexts in their type signatures have been strengthened fromQuasitoDsMonad.
- 
Export a dTyVarBndrToDTypefunction which converts aDTyVarBndrto aDType, which preserves its kind.
- 
Previously, th-desugarwould silently accept illegal uses of record construction with fields that did not belong to the constructor, such asIdentity { notAField = "wat" }. This is now an error.
Version 1.8
- 
Support GHC 8.4. 
- 
substTynow properly substitutes into kind signatures.
- 
Expose fvDType, which computes the free variables of aDType.
- 
Incorporate a DDeclaredInfixfield intoDNormalCto indicate if it is a constructor that was declared infix.
- 
Implement lookupValueNameWithLocals,lookupTypeNameWithLocals,mkDataNameWithLocals, andmkTypeNameWithLocals, counterparts tolookupValueName,lookupTypeName,mkDataName, andmkTypeNamewhich have access to local Template Haskell declarations.
- 
Implement reifyNameSpaceto determine aName’sNameSpace.
- 
Export reifyFixityWithLocalsfromLanguage.Haskell.TH.Desugar.
- 
Export matchTy(among other goodies) from new moduleLanguage.Haskell.TH.Subst. This function matches a type template against a target.
Version 1.7
- 
Support for TH’s support for TypeApplications, thanks to @RyanGlScott.
- 
Support for unboxed sums, thanks to @RyanGlScott. 
- 
Support for COMPLETEpragmas.
- 
getRecordSelectorsnow requires a list ofDCons as an argument. This makes it easier to return correct record selector bindings in the event that a record selector appears in multiple constructors. (See goldfirere/singletons#180 for an example of where the old behavior ofgetRecordSelectorswent wrong.)
- 
Better type family expansion (expanding an open type family with variables works now). 
Version 1.6
- 
Work with GHC 8, with thanks to @christiaanb for getting this change going. This means that several core datatypes have changed: partcularly, we now have DTypeFamilyHeadand fixities are now reified separately from other things.
- 
DKindis merged withDType.
- 
Genericinstances for everything.
Version 1.5.5
- Fix issue #34. This means that desugaring (twice) is idempotent over expressions, after the second time. That is, if you desugar an expression, sweeten it, desugar again, sweeten again, and then desugar a third time, you get the same result as when you desugared the second time. (The extra round-trip is necessary there to make the output smaller in certain common cases.)
Version 1.5.4.1
- Fix issue #32, concerning reification of classes with default methods.
Version 1.5.4
- Added expandUnsoundly
Version 1.5.3
- More DsMonadinstances, thanks to David Fox.
Version 1.5.2
- Sweeten kinds more, too.
Version 1.5.1
- 
Thanks to David Fox (@ddssff), sweetening now tries to use more of TH’s Typeconstructors.
- 
Also thanks to David Fox, depend usefully on the th-orphans package. 
Version 1.5
- 
There is now a facility to register a list of Decthat internal reification should use when necessary. This avoids the user needing to break up their definition across different top-level splices. SeewithLocalDeclarations. This has a side effect of changing theQuasitypeclass constraint on many functions to be the newDsMonadconstraint. Happily, there areDsMonadinstances forQandIO, the two normal inhabitants ofQuasi.
- 
“Match flattening” is implemented! The functions scExpandscLetDecremove any nested pattern matches.
- 
More is now exported from Language.Haskell.TH.Desugarfor ease of use.
- 
expandcan now expand closed type families! It still requires that the type to expand contain no type variables.
- 
Support for standalone-deriving and default signatures in GHC 7.10. This means that there are now two new constructors for DDec.
- 
Support for staticexpressions, which are new in GHC 7.10.
Version 1.4.2
- expandfunctions now consider open type families, as long as the type to be expanded has no free variables.
Version 1.4.1
- 
Added Language.Haskell.TH.Desugar.Lift, which providesLiftinstances for all of the th-desugar types, as well as several Template Haskell types.
- 
Added applyDExpandapplyDTypeas convenience functions.
Version 1.4.0
- 
All Decs can now be desugared, to the newDDectype.
- 
Sweetening Decs that do not exist in GHC 7.6.3- works on a “best effort” basis: closed type families are sweetened to open ones, and role annotations are dropped.
- 
Infos can now be desugared. Desugaring takes into account GHC bug #8884, which meant that reifying poly-kinded type families in GHC 7.6.3- was subtly wrong.
- 
There is a new function flattenDValDwhich takes a binding likelet (a,b) = fooand breaks it apart into separate assignments foraandb.
- 
There is a new Desugarclass with methodsdesugarandsweeten. See the documentation inLanguage.Haskell.TH.Desugar.
- 
Variable names that are distinct in desugared code are now guaranteed to have distinct answers to nameBase.
- 
Added a new function getRecordSelectorsthat extracts types and definitions of record selectors from a datatype definition.
Version 1.3.1
- Update cabal file to include testing files in sdist.
Version 1.3.0
- Update to work with type Pred = Typein GHC 7.9. This changed theDPredtype for all GHC versions, though.
Version 1.2.0
- Generalized interface to allow any member of the Qausiclass, instead of justQ.
Version 1.1.1
- Made compatible with HEAD after change in role annotation syntax.
Version 1.1
- Added module Language.Haskell.TH.Desugar.Expand, which allows for expansion of type synonyms in desugared types.
- Added Show,Typeable, andDatainstances to desugared types.
- Fixed bug where an as-pattern in a letstatement was scoped incorrectly.
- Changed signature of dsPatto be more specific to as-patterns; this allowed for fixing theletscoping bug.
- Created new functions dsPatOverExpanddsPatsOverExpto allow for easy desugaring of patterns.
- Changed signature of dsLetDecto return a list ofDLetDecs.
- Added dsLetDecsfor convenience. Now, instead of usingmapM dsLetDec, you should usedsLetDecs.
Version 1.0
- Initial release
