| Maintainer | emertens@gmail.com |
|---|---|
| Safe Haskell | None |
Language.Haskell.TH.Datatype
Contents
Description
This module provides a flattened view of information about data types and newtypes that can be supported uniformly across multiple versions of the template-haskell package.
Sample output for reifyDatatype ''Maybe
DatatypeInfo{datatypeContext= [] ,datatypeName= GHC.Base.Maybe ,datatypeVars= [SigT(VarTa_3530822107858468866)StarT] ,datatypeVariant=Datatype,datatypeCons= [ConstructorInfo{constructorName= GHC.Base.Nothing ,constructorVars= [] ,constructorContext= [] ,constructorFields= [] ,constructorStrictness= [] ,constructorVariant=NormalConstructor} ,ConstructorInfo{constructorName= GHC.Base.Just ,constructorVars= [] ,constructorContext= [] ,constructorFields= [VarTa_3530822107858468866 ] ,constructorStrictness= [FieldStrictnessUnspecifiedUnpackednessLazy] ,constructorVariant=NormalConstructor} ] }
Datatypes declared with GADT syntax are normalized to constructors with existentially quantified type variables and equality constraints.
- data DatatypeInfo = DatatypeInfo {
- datatypeContext :: Cxt
- datatypeName :: Name
- datatypeVars :: [Type]
- datatypeVariant :: DatatypeVariant
- datatypeCons :: [ConstructorInfo]
- data ConstructorInfo = ConstructorInfo {
- constructorName :: Name
- constructorVars :: [TyVarBndr]
- constructorContext :: Cxt
- constructorFields :: [Type]
- constructorStrictness :: [FieldStrictness]
- constructorVariant :: ConstructorVariant
- data DatatypeVariant
- = Datatype
- | Newtype
- | DataInstance
- | NewtypeInstance
- data ConstructorVariant
- = NormalConstructor
- | InfixConstructor
- | RecordConstructor [Name]
- data FieldStrictness = FieldStrictness {}
- data Unpackedness
- data Strictness
- = UnspecifiedStrictness
- | Lazy
- | Strict
- reifyDatatype :: Name -> Q DatatypeInfo
- reifyConstructor :: Name -> Q ConstructorInfo
- reifyRecord :: Name -> Q ConstructorInfo
- normalizeInfo :: Info -> Q DatatypeInfo
- normalizeDec :: Dec -> Q DatatypeInfo
- normalizeCon :: Name -> [Type] -> DatatypeVariant -> Con -> Q [ConstructorInfo]
- lookupByConstructorName :: Name -> DatatypeInfo -> ConstructorInfo
- lookupByRecordName :: Name -> DatatypeInfo -> ConstructorInfo
- class TypeSubstitution a where
- applySubstitution :: Map Name Type -> a -> a
- freeVariables :: a -> [Name]
- quantifyType :: Type -> Type
- freshenFreeVariables :: Type -> Q Type
- equalPred :: Type -> Type -> Pred
- classPred :: Name -> [Type] -> Pred
- asEqualPred :: Pred -> Maybe (Type, Type)
- asClassPred :: Pred -> Maybe (Name, [Type])
- dataDCompat :: CxtQ -> Name -> [TyVarBndr] -> [ConQ] -> [Name] -> DecQ
- newtypeDCompat :: CxtQ -> Name -> [TyVarBndr] -> ConQ -> [Name] -> DecQ
- tySynInstDCompat :: Name -> [TypeQ] -> TypeQ -> DecQ
- pragLineDCompat :: Int -> String -> Maybe DecQ
- arrowKCompat :: Kind -> Kind -> Kind
- isStrictAnnot :: FieldStrictness
- notStrictAnnot :: FieldStrictness
- unpackedAnnot :: FieldStrictness
- resolveTypeSynonyms :: Type -> Q Type
- resolvePredSynonyms :: Pred -> Q Pred
- resolveInfixT :: Type -> Q Type
- reifyFixityCompat :: Name -> Q (Maybe Fixity)
- showFixity :: Fixity -> String
- showFixityDirection :: FixityDirection -> String
- unifyTypes :: [Type] -> Q (Map Name Type)
- tvName :: TyVarBndr -> Name
- tvKind :: TyVarBndr -> Kind
- datatypeType :: DatatypeInfo -> Type
Types
data DatatypeInfo
Normalized information about newtypes and data types.
datatypeVars types will have an outermost SigT to indicate the
parameter's kind. These types will be simple variables for ADTs
declared with data and newtype, but can be more complex for
types declared with data instance and newtype instance.
Constructors
| DatatypeInfo | |
Fields
| |
Instances
| Eq DatatypeInfo | |
| Data DatatypeInfo | |
| Show DatatypeInfo | |
| Typeable DatatypeInfo | |
| Generic DatatypeInfo |
data ConstructorInfo
Normalized information about constructors associated with newtypes and data types.
Constructors
| ConstructorInfo | |
Fields
| |
Instances
| Eq ConstructorInfo | |
| Data ConstructorInfo | |
| Show ConstructorInfo | |
| Typeable ConstructorInfo | |
| Generic ConstructorInfo | |
| TypeSubstitution ConstructorInfo |
data DatatypeVariant
Possible variants of data type declarations.
Constructors
| Datatype | Type declared with |
| Newtype | Type declared with |
| DataInstance | Type declared with |
| NewtypeInstance | Type declared with |
Instances
| Eq DatatypeVariant | |
| Data DatatypeVariant | |
| Ord DatatypeVariant | |
| Read DatatypeVariant | |
| Show DatatypeVariant | |
| Typeable DatatypeVariant | |
| Generic DatatypeVariant |
data ConstructorVariant
Possible variants of data constructors.
Constructors
| NormalConstructor | Constructor without field names |
| InfixConstructor | Constructor without field names that is declared infix |
| RecordConstructor [Name] | Constructor with field names |
Instances
| Eq ConstructorVariant | |
| Data ConstructorVariant | |
| Ord ConstructorVariant | |
| Show ConstructorVariant | |
| Typeable ConstructorVariant | |
| Generic ConstructorVariant |
data FieldStrictness
Normalized information about a constructor field's UNPACK and
strictness annotations.
Note that the interface for reifying strictness in Template Haskell changed considerably in GHC 8.0. The presentation in this library mirrors that which can be found in GHC 8.0 or later, whereas previously, unpackedness and strictness were represented with a single data type:
data Strict = IsStrict | NotStrict | Unpacked -- On GHC 7.4 or later
For backwards compatibility, we retrofit these constructors onto the following three values, respectively:
isStrictAnnot=FieldStrictnessUnspecifiedUnpackednessStrictnotStrictAnnot=FieldStrictnessUnspecifiedUnpackednessUnspecifiedStrictnessunpackedAnnot=FieldStrictnessUnpackStrict
Constructors
| FieldStrictness | |
Fields | |
Instances
| Eq FieldStrictness | |
| Data FieldStrictness | |
| Ord FieldStrictness | |
| Show FieldStrictness | |
| Typeable FieldStrictness | |
| Generic FieldStrictness |
data Unpackedness
Information about a constructor field's unpackedness annotation.
Constructors
| UnspecifiedUnpackedness | No annotation whatsoever |
| NoUnpack | Annotated with |
| Unpack | Annotated with |
Instances
| Eq Unpackedness | |
| Data Unpackedness | |
| Ord Unpackedness | |
| Show Unpackedness | |
| Typeable Unpackedness | |
| Generic Unpackedness |
data Strictness
Information about a constructor field's strictness annotation.
Constructors
| UnspecifiedStrictness | No annotation whatsoever |
| Lazy | Annotated with |
| Strict | Annotated with |
Instances
| Eq Strictness | |
| Data Strictness | |
| Ord Strictness | |
| Show Strictness | |
| Typeable Strictness | |
| Generic Strictness |
Normalization functions
Arguments
| :: Name | data type or constructor name |
| -> Q DatatypeInfo |
Compute a normalized view of the metadata about a data type or newtype given a constructor.
This function will accept any constructor (value or type) for a type declared with newtype or data. Value constructors must be used to lookup datatype information about data instances and newtype instances, as giving the type constructor of a data family is often not enough to determine a particular data family instance.
In addition, this function will also accept a record selector for a data type with a constructor which uses that record.
GADT constructors are normalized into datatypes with explicit equality constraints. Note that no effort is made to distinguish between equalities of the same (homogeneous) kind and equalities between different (heterogeneous) kinds. For instance, the following GADT's constructors:
data T (a :: k -> *) where MkT1 :: T Proxy MkT2 :: T Maybe
will be normalized to the following equality constraints:
AppT (AppT EqualityT (VarT a)) (ConT Proxy) -- MkT1 AppT (AppT EqualityT (VarT a)) (ConT Maybe) -- MkT2
But only the first equality constraint is well kinded, since in the second
constraint, the kinds of (a :: k -> *) and (Maybe :: * -> *) are different.
Trying to categorize which constraints need homogeneous or heterogeneous
equality is tricky, so we leave that task to users of this library.
This function will apply various bug-fixes to the output of the underlying
template-haskell library in order to provide a view of datatypes in
as uniform a way as possible.
Arguments
| :: Name | constructor name |
| -> Q ConstructorInfo |
Compute a normalized view of the metadata about a constructor given its
Name. This is useful for scenarios when you don't care about the info for
the enclosing data type.
Arguments
| :: Name | record name |
| -> Q ConstructorInfo |
Compute a normalized view of the metadata about a constructor given the
Name of one of its record selectors. This is useful for scenarios when you
don't care about the info for the enclosing data type.
normalizeInfo :: Info -> Q DatatypeInfo
Normalize Info for a newtype or datatype into a DatatypeInfo.
Fail in Q otherwise.
normalizeDec :: Dec -> Q DatatypeInfo
Normalize Dec for a newtype or datatype into a DatatypeInfo.
Fail in Q otherwise.
Beware: normalizeDec can have surprising behavior when it comes to fixity.
For instance, if you have this quasiquoted data declaration:
[d| infix 5 :^^:
data Foo where
(:^^:) :: Int -> Int -> Foo |]
Then if you pass the Dec for Foo to normalizeDec without splicing it
in a previous Template Haskell splice, then (:^^:) will be labeled a NormalConstructor
instead of an InfixConstructor. This is because Template Haskell has no way to
reify the fixity declaration for (:^^:), so it must assume there isn't one. To
work around this behavior, use reifyDatatype instead.
Arguments
| :: Name | Type constructor |
| -> [Type] | Type parameters |
| -> DatatypeVariant | Extra information |
| -> Con | Constructor |
| -> Q [ConstructorInfo] |
Normalize a Con into a ConstructorInfo. This requires knowledge of
the type and parameters of the constructor, as well as whether the constructor
is for a data family instance, as extracted from the outer
Dec.
DatatypeInfo lookup functions
Arguments
| :: Name | constructor name |
| -> DatatypeInfo | info for the datatype which has that constructor |
| -> ConstructorInfo |
Given a DatatypeInfo, find the ConstructorInfo corresponding to the
Name of one of its constructors.
Arguments
| :: Name | record name |
| -> DatatypeInfo | info for the datatype which has that constructor |
| -> ConstructorInfo |
Given a DatatypeInfo, find the ConstructorInfo corresponding to the
Name of one of its constructors.
Type variable manipulation
class TypeSubstitution a where
Class for types that support type variable substitution.
Methods
applySubstitution :: Map Name Type -> a -> a
Apply a type variable substitution.
Note that applySubstitution is not capture-avoiding. To illustrate
this, observe that if you call this function with the following
substitution:
b :-> a
On the following Type:
forall a. b
Then it will return:
forall a. a
However, because the same a type variable was used in the range of the
substitution as was bound by the forall, the substituted a is now
captured by the forall, resulting in a completely different function.
For th-abstraction's purposes, this is acceptable, as it usually only
deals with globally unique type variable Names. If you use
applySubstitution in a context where the Names aren't globally unique,
however, be aware of this potential problem.
freeVariables :: a -> [Name]
Compute the free type variables
Instances
| TypeSubstitution Type | |
| TypeSubstitution Pred | |
| TypeSubstitution ConstructorInfo | |
| TypeSubstitution a => TypeSubstitution [a] |
quantifyType :: Type -> Type
Add universal quantifier for all free variables in the type. This is
useful when constructing a type signature for a declaration.
This code is careful to ensure that the order of the variables quantified
is determined by their order of appearance in the type signature. (In
contrast with being dependent upon the Ord instance for Name)
freshenFreeVariables :: Type -> Q Type
Substitute all of the free variables in a type with fresh ones
Pred functions
equalPred :: Type -> Type -> Pred
Construct an equality constraint. The implementation of Pred varies
across versions of Template Haskell.
Arguments
| :: Name | class |
| -> [Type] | parameters |
| -> Pred |
Construct a typeclass constraint. The implementation of Pred varies
across versions of Template Haskell.
asEqualPred :: Pred -> Maybe (Type, Type)
Match a Pred representing an equality constraint. Returns
arguments to the equality constraint if successful.
asClassPred :: Pred -> Maybe (Name, [Type])
Match a Pred representing a class constraint.
Returns the classname and parameters if successful.
Backward compatible data definitions
Arguments
| :: CxtQ | context |
| -> Name | type constructor |
| -> [TyVarBndr] | type parameters |
| -> [ConQ] | constructor definitions |
| -> [Name] | derived class names |
| -> DecQ |
Backward compatible version of dataD
Arguments
| :: CxtQ | context |
| -> Name | type constructor |
| -> [TyVarBndr] | type parameters |
| -> ConQ | constructor definition |
| -> [Name] | derived class names |
| -> DecQ |
Backward compatible version of newtypeD
Arguments
| :: Name | type family name |
| -> [TypeQ] | instance parameters |
| -> TypeQ | instance result |
| -> DecQ |
Backward compatible version of tySynInstD
Arguments
| :: Int | line number |
| -> String | file name |
| -> Maybe DecQ |
Backward compatible version of pragLineD. Returns
Nothing if line pragmas are not suported.
arrowKCompat :: Kind -> Kind -> Kind
Strictness annotations
Type simplification
resolveTypeSynonyms :: Type -> Q Type
Expand all of the type synonyms in a type.
resolvePredSynonyms :: Pred -> Q Pred
Expand all of the type synonyms in a Pred.
resolveInfixT :: Type -> Q Type
Resolve any infix type application in a type using the fixities that are currently available. Starting in `template-haskell-2.11` types could contain unresolved infix applications.
Fixities
reifyFixityCompat :: Name -> Q (Maybe Fixity)
Backwards compatibility wrapper for Fixity lookup.
In template-haskell-2.11.0.0 and later, the answer will always
be Just of a fixity.
Before template-haskell-2.11.0.0 it was only possible to determine
fixity information for variables, class methods, and data constructors.
In this case for type operators the answer could be Nothing, which
indicates that the answer is unavailable.
showFixity :: Fixity -> String
Render a Fixity as it would appear in Haskell source.
Example: infixl 5
showFixityDirection :: FixityDirection -> String
Render a FixityDirection like it would appear in Haskell source.
Examples: infixl infixr infix
Convenience functions
unifyTypes :: [Type] -> Q (Map Name Type)
Compute the type variable substitution that unifies a list of types,
or fail in Q.
All infix issue should be resolved before using unifyTypes
Alpha equivalent quantified types are not unified.
tvName :: TyVarBndr -> Name
Extract the type variable name from a TyVarBndr ignoring the
kind signature if one exists.
tvKind :: TyVarBndr -> Kind
Extract the kind from a TyVarBndr. Assumes PlainTV has kind *.
datatypeType :: DatatypeInfo -> Type
Construct a Type using the datatype's type constructor and type parameters. Kind signatures are removed.