th-abstraction
Nicer interface for reified information about data types
https://github.com/glguy/th-abstraction
Version on this page: | 0.7.0.0 |
LTS Haskell 23.1: | 0.7.1.0 |
Stackage Nightly 2024-12-21: | 0.7.1.0 |
Latest on Hackage: | 0.7.1.0 |
th-abstraction-0.7.0.0@sha256:4d80fe53ed140866018278c81e1c0c9bc8fc73d8f2a530321a588f24be491fc4,2248
Module documentation for 0.7.0.0
- Language
- Language.Haskell
- Language.Haskell.TH
- Language.Haskell
th-abstraction
This package provides a consistent interface to a subset of Template Haskell.
Currently the package provides a consistent view of the reified declaration information about datatypes, newtypes, and data family instances. These interfaces abstract away the differences in the normal and GADT syntax used to define these types.
Contact Information
Please contact me via GitHub or on the #haskell IRC channel on irc.libera.chat
Changes
Revision history for th-abstraction
0.7.0.0 – 2024.03.17
DatatypeInfo
now has an additionaldatatypeReturnKind
field. Most of the time, this will beStarT
, but this can also be more exotic kinds such asConT ''UnliftedType
if dealing with primitive types,UnliftedDatatypes
, orUnliftedNewtypes
.reifyDatatype
and related functions now support primitive types such asInt#
. These will be reified asDatatypeInfo
s with noConstructorInfo
s and withDatatype
as thedatatypeVariant
.normalizeCon
now takes aKind
argument representing the return kind of the parent data type. (This is sometimes necessary to determine which type variables in the data constructor are universal or existential, depending on if the variables appear in the return kind.)- Fix a couple of bugs in which
normalizeDec
would return incorrect results for GADTs that useforall
s in their return kind.
0.6.0.0 – 2023.07.31
-
Support building with
template-haskell-2.21.0.0
(GHC 9.8). -
Adapt to
TyVarBndr
s for type-level declarations changing their type fromTyVarBndr ()
toTyVarBndr BndrVis
intemplate-haskell
:Language.Haskell.TH.Datatype.TyVarBndr
now backportstype BndrVis = ()
, as well asBndrReq
andBndrInvis
pattern synonyms. These make it possible to write code involvingBndrVis
that is somewhat backwards compatible (but do see the caveats in the Haddocks forBndrInvis
).Language.Haskell.TH.Datatype.TyVarBndr
also backports the following definitions:- The
type TyVarBndrVis = TyVarBndr BndrVis
type synonym. - The
DefaultBndrFlag
class, which can be used to write code that is polymorphic overTyVarBndr
flags while still allowing the code to return a reasonable default value for the flag. - The
bndrReq
andbndrInvis
definitions, which behave identically toBndrReq
andBndrInvis
.
- The
Language.Haskell.TH.Datatype.TyVarBndr
now defines the following utility functions, which are not present intemplate-haskell
:plainTVReq
,plainTVInvis
,kindedTVReq
, andkindedTVInvis
functions, which constructPlainTV
s andKindedTV
s with particularBndrVis
flags.- An
elimTVFlag
, which behaves likeelimTV
, but where the continuation arguments also take aflag
argument. (Note that the type of this function is slightly different on old versions oftemplate-haskell
. See the Haddocks for more.) - A
tvFlag
function, which extracts theflag
from aTyVarBndr
. (Note that the type of this function is slightly different on old versions oftemplate-haskell
. See the Haddocks for more.)
- The types of the
dataDCompat
andnewtypeDCompat
functions have had their[TyVarBndrUnit]
arguments changed to[TyVarBndrVis]
, matching similar changes toDataD
andNewtypeD
intemplate-haskell
.
Because
BndrVis
is a synonym for()
on pre-9.8 versions of GHC, this change is unlikely to break any existing code, provided that you build it with GHC 9.6 or earlier. If you build with GHC 9.8 or later, on the other hand, it is likely that you will need to update your existing code. Here are some possible ways that your code might fail to compile with GHC 9.8, along with some migration strategies:-
Your code passes a
TyVarBndrUnit
in a place where aTyVarBndrVis
is now expected in GHC 9.8, such as in the arguments todataDCompat
:import "template-haskell" Language.Haskell.TH import "th-abstraction" Language.Haskell.TH.Datatype (dataDCompat) dec :: DecQ dec = dataDCompat (pure []) d [PlainTV a ()] [] [] where d = mkName "d" a = mkName "a"
With GHC 9.8, this will fail to compile with:
error: [GHC-83865] • Couldn't match expected type ‘BndrVis’ with actual type ‘()’ • In the second argument of ‘PlainTV’, namely ‘()’ In the expression: PlainTV a () In the third argument of ‘dataDCompat’, namely ‘[PlainTV a ()]’ | | dec = dataDCompat (pure []) d [PlainTV a ()] [] [] | ^^
Some possible ways to migrate this code include:
-
Use the
bndrReq
function orBndrReq
pattern synonym in place of()
, making sure to import them fromLanguage.Haskell.TH.Datatype.TyVarBndr
:... import "th-abstraction" Language.Haskell.TH.Datatype.TyVarBndr dec :: DecQ dec = dataDCompat (pure []) d [PlainTV a bndrReq] [] [] -- Or, alternatively: {- dec = dataDCompat (pure []) d [PlainTV a BndrReq] [] [] -} where ...
-
Use the
plainTV
function fromLanguage.Haskell.TH.Datatype.TyVarBndr
, which is now sufficiently polymorphic to work as both aTyVarBndrUnit
and aTyVarBndrVis
:... import Language.Haskell.TH.Datatype.TyVarBndr dec :: DecQ dec = dataDCompat (pure []) d [plainTV a] [] [] where ...
-
-
You may have to replace some uses of
TyVarBndrUnit
withTyVarBndrVis
in your code. For instance, this will no longer typecheck in GHC 9.8 for similar reasons to the previous example:import "template-haskell" Language.Haskell.TH import "th-abstraction" Language.Haskell.TH.Datatype (dataDCompat) dec :: DecQ dec = dataDCompat (pure []) d tvbs [] [] where tvbs :: [TyVarBndrUnit] tvbs = [plainTV a] d = mkName "d" a = mkName "a"
Here is a version that will typecheck with GHC 9.8 and earlier:
... import "th-abstraction" Language.Haskell.TH.Datatype.TyVarBndr dec :: DecQ dec = dataDCompat (pure []) d tvbs [] [] where tvbs :: [TyVarBndrVis] tvbs = [plainTV a] ...
-
In some cases, the
TyVarBndrUnit
s might come from another place in the code, e.g.,import "template-haskell" Language.Haskell.TH import "th-abstraction" Language.Haskell.TH.Datatype (dataDCompat) dec :: [TyVarBndrUnit] -> DecQ dec tvbs = dataDCompat (pure []) d tvbs [] [] where d = mkName "d"
If it is not straightforward to change
dec
’s type to accept[TyVarBndrVis]
as an argument, another viable option is to use thechangeTVFlags
function:... import "th-abstraction" Language.Haskell.TH.Datatype.TyVarBndr dec :: [TyVarBndrUnit] -> DecQ dec tvbs = dataDCompat (pure []) d tvbs' [] [] where tvbs' :: [TyVarBndrVis] tvbs' = changeTVFlags bndrReq tvbs ...
This guide, while not comprehensive, should cover most of the common cases one will encounter when migrating their
th-abstraction
code to support GHC 9.8.
0.5.0.0 – 2023.02.27
- Support the
TypeData
language extension added in GHC 9.6. TheDatatypeVariant
data type now has a separateTypeData
constructor to representtype data
declarations. - Add a
Lift
instance forth-abstraction
’s compatibility shim forSpecificity
when building with pre-9.0 versions of GHC.
0.4.5.0 – 2022.09.12
- Fix a bug in which data family declarations with interesting return kinds
(e.g.,
data family F :: Type -> Type
) would be reified incorrectly when usingreifyDatatype
.
0.4.4.0 – 2022.07.23
- Support free variable substitution and infix resolution for
PromotedInfixT
andPromotedUInfixT
ontemplate-haskell-2.19.0.0
or later.
0.4.3.0 – 2021.08.30
- Make
applySubstitution
avoid capturing type variable binders when substituting intoforall
s. - Fix a bug in which
resolveTypeSynonyms
would incorrectly expand type synonyms that are not applied to enough arguments. - Allow the test suite to build with GHC 9.2.
0.4.2.0 – 2020-12-30
- Explicitly mark modules as Safe (or Trustworthy for GHC versions prior to 8.4).
0.4.1.0 – 2020-12-09
- Fix a bug in which
normalizeDec
would give incorrect kind annotations to type variables in quotedDec
s.normalizeDec
now leaves the kinds of type variable binders alone.
0.4.0.0 – 2020-09-29
- Adapt to the
TyVarBndr
data type gaining a newflag
type parameter (intemplate-haskell-2.17.0.0
) to represent its specificity:- Introduce a new
Language.Haskell.TH.Datatype.TyVarBndr
module that definesTyVarBndr_
, a backwards-compatible type synonym forTyVarBndr
, as well as backportingTyVarBndrSpec
,TyVarBndrUnit
, andSpecificity
. This module also defines other useful functions for constructing and manipulatingTyVarBndr
s. - The types in
Language.Haskell.TH.Datatype
now useTyVarBndr_
,TyVarBndrUnit
, andTyVarBndrSpec
where appropriate. Technically, this is not a breaking change, since all three are simple type synonyms aroundTyVarBndr
, but it is likely that you will need to update yourth-abstraction
-using code anyway if it involves aTyVarBndr
-consuming function.
- Introduce a new
0.3.2.0 – 2020-02-06
- Support substituting into and extracting free variables from
ForallVisT
s ontemplate-haskell-2.16.0.0
(GHC 8.10) or later. - Fix a bug in which
freeVariables
could report duplicate kind variables when they occur in the kinds of the type variable binders in aForallT
. - Fix a bug in which
resolveInfixT
would not resolveUInfixT
s occurring in the kinds of type variable binders in aForallT
. - Fix a bug in which the
TypeSubstitution ConstructorInfo
instance would not detect free kind variables in theconstructorVars
.
0.3.1.0 – 2019-04-28
- Fix a bug which would cause data family information to be reified incorrectly with GHC 8.8+ in some situations.
0.3.0.0 – 2019-04-26
-
Breaking change: the
datatypeVars
field ofDatatypeInfo
is now of type[TyVarBndr]
instead of[Type]
, as it now refers to all of the bound type variables in the data type. The olddatatypeVars
field has been renamed todatatypeInstTypes
to better reflect its purpose.In addition, the type of
normalizeCon
now has an additional[TyVarBndr]
argument, sinceDatatypeInfo
now requires it. -
Support
template-haskell-2.15
. -
Fix a bug in which
normalizeDec
would not detect existential type variables in a GADT constructor if they were implicitly quantified. -
Fix a bug in which
normalizeDec
would report an incorrect number ofdatatypeVars
for GADT declarations with explicit return kinds (such asdata Foo :: * -> * where
).
0.2.11.0 – 2019-02-26
- Fix a bug in which
freeVariablesWellScoped
would sometimes not preserve the left-to-right ordering ofName
s generated withnewName
.
0.2.10.0 – 2018-12-20
- Optimization:
quantifyType
now collapses consecutiveforall
s. For instance, callingquantifyType
onforall b. a -> b -> T a
now producesforall a b. a -> b -> T a
instead offorall a. forall b. a -> b -> T a
.
0.2.9.0 – 2018-12-20
- Fix a bug in which
resolveTypeSynonyms
would not look intoForallT
s,SigT
s,InfixT
s, orParensT
s. - Fix a bug in which
quantifyType
would not respect the dependency order of type variables (e.g.,Proxy (a :: k)
would have erroneously been quantified asforall a k. Proxy (a :: k)
). - Fix a bug in which
asEqualPred
would return incorrect results with GHC 8.7. - Add a
freeVariablesWellScoped
function which computes the free variables of a list of types and sorts them according to dependency order. - Add a
resolveKindSynonyms
function which expands all type synonyms in aKind
. This is mostly useful for supporting old GHCs whereType
andKind
were not the same.
0.2.8.0 – 2018-06-29
- GADT reification is now much more robust with respect to
PolyKinds
:-
A bug in which universally quantified kind variables were mistakenly flagged as existential has been fixed.
-
A bug in which the kinds of existentially quantified type variables were not substituted properly has been fixed.
-
More kind equalities are detected than before. For example, in the following data type:
data T (a :: k) where MkT :: forall (a :: Bool). T a
We now catch the
k ~ Bool
equality.
-
- Tweak
resolveTypeSynonyms
so that failing to reify a type constructor name so longer results in an error. Among other benefits, this makes it possible to pass data types with GADT syntax tonormalizeDec
.
0.2.7.0 – 2018-06-17
- Fix bug in which data family instances with duplicate occurrences of type variables in the left-hand side would have redundant equality constraints in their contexts.
0.2.6.0 – 2017-09-04
- Fix bug in which
applySubstitution
andfreeVariables
would ignore type variables in the kinds of type variable binders.
0.2.5.0
- Added
pragLineDCompat
,newtypeDCompat
andtySynInstDCompat
0.2.4.0 – 2017-07-31
- Fix bug that caused GADT equality constraints to be incorrect in some cases.
- Expose
Unpackedness
andStrictness
(which were unexported by accident).
0.2.3.0 – 2017-06-26
- Add
resolvePredSynonyms
- Add
reifyConstructor
, which allows reification ofConstructorInfo
from a constructor name, andlookupByConstructorName
, which allows directly looking up aConstructorInfo
from aDatatypeInfo
value for a given constructorName
. - Augment
reifyDatatype
to be able to look upDatatypeInfo
from theName
of a record selector for one of its constructors. Also addreifyRecord
for reification of ofConstructorInfo
from a record name, andlookupByRecordName
, which allows directly looking up aConstructorInfo
from aDatatypeInfo
value for a given recordName
. - Fix bug that caused
th-abstraction
to fail on GHC 7.0 and 7.2 when passing a vanilla constructor name toreifyDatatype
- Make
normalizeDec
andnormalizeCon
more robust with respect to data family instances on GHC 7.6 and 7.8
0.2.2.0 – 2017-06-10
- Fix
freeVariables
on lists not not produce duplicates.
0.2.1.0 – 2017-06-09
- Add sensible reify defaults and error messages when we can’t backport fixes to old GHC Template Haskell output due to hand-written Decs being processed.
0.2.0.0 – 2017-06-03
- Added
reifyFixityCompat
- Added
constructorStrictness
field toConstructorInfo
- Infer more kind signatures when missing on old GHCs
- Added parameter to
normalizeCon
- Support GHC back to 7.0.4
0.1.3.0 – 2017-05-27
- Added
resolveInfixT
which uses reified fixity information to resolveUInfixT
- Added
asEqualPred
andasClassPred
- Fixed data-instance GADTs
0.1.2.1 – 2017-05-21
- Add eta reduction fixes to GHC 7.6
0.1.2.0 – 2017-05-21
- Added
arrowKCompat
- Added workaround for GHC 7.8 data instance eta reduction bug
- Added kind signatures to datatypeVars
0.1.1.0 – 2017-05-20
- Better matching of constraints generated for GADTs across GHC versions
- Added
dataDCompat
- Support for giving value constructors to reifyDatatype. This enables data families to be reified easily.
0.1.0.0 – 2017-04-26
- First version.