th-desugar v1.12 Release Notes
-
- ๐ Support GHC 9.0.
โ Add support for explicit specificity. As part of this change, the way
th-desugar
represents type variable binders has been overhauled:- The
DTyVarBndr
data type is now parameterized by aflag
type parameter:
data DTyVarBndr flag = DPlainTV Name flag | DKindedTV Name flag DKind
This can be instantiated to
Specificity
(for type variable binders that can be specified or inferred) or()
(for type variable binders where specificity is irrelevant).DTyVarBndrSpec
andDTyVarBndrUnit
are also provided as type synonyms forDTyVarBndr Specificity
andDTyVarBndr ()
, respectively.- In order to interface with
TyVarBndr
(the TH counterpart toDTyVarBndr
) in a backwards-compatible way,th-desugar
now depends on theth-abstraction
library. - The
ForallVisFlag
has been removed in favor of the newDForallTelescope
data type, which not only distinguishes between invisible and visibleforall
s but also uses the correct type variable flag for invisible type variables (Specificity
) and visible type variables (()
). - The type of the
dsTvb
is 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) #endif
This is unfortunately required by the fact that prior to GHC 9.0, there is no
flag
information stored anywhere in aTyVarBndr
. If you need to usedsTvb
in a backward-compatible way,L.H.TH.Desugar
now providesdsTvbSpec
anddsTvbUnit
functions which specialisedsTvb
to particularflag
types:dsTvbSpec :: DsMonad q => TyVarBndrSpec -> q DTyVarBndrSpec dsTvbUnit :: DsMonad q => TyVarBndrUnit -> q DTyVarBndrUnit
- The
The type of the
getRecordSelectors
function has changed:
-getRecordSelectors :: DsMonad q => DType -> [DCon] -> q [DLetDec] +getRecordSelectors :: DsMonad q => [DCon] -> q [DLetDec]
The old type signature had a
DType
argument 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 f
The old implementation of
getRecordSelectors
would not includegetSome
in the returned list, as its typef a
mentions 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
conExistentialTvbs
function has been removed. It was horribly buggy, especially in the presence of GADT constructors. Moreover, this function was used in the implementation ofgetRecordSelectors
function, so bugs inconExistentialTvbs
often affected the results ofgetRecordSelectors
. - The types of
decToTH
,letDecToTH
, andpragmaToTH
have changed:
-decToTH :: DDec -> [Dec] +decToTH :: DDec -> Dec -letDecToTH :: DLetDec -> Maybe Dec +letDecToTH :: DLetDec -> Dec -pragmaToTH :: DPragma -> Maybe Pragma +pragmaToTH :: DPragma -> Pragma
The semantics of
pragmaToTH
have changed accordingly. Previously,pragmaToTH
would returnNothing
when the argument is aDPragma
that is not supported on an old version of GHC, but now an error will be thrown instead.decToTH
andletDecToTH
, which transitively invokepragmaToTH
, have had their types updated to accommodatepragmaToTH
's type change.- The type of the
substTyVarBndrs
function 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])