generic-deriving 1.10.7 → 1.11
raw patch · 5 files changed
+533/−274 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Generics.Deriving.TH: deriveAll0And1WithKindSigs :: Name -> Q [Dec]
- Generics.Deriving.TH: deriveAll0WithKindSigs :: Name -> Q [Dec]
- Generics.Deriving.TH: deriveAll1WithKindSigs :: Name -> Q [Dec]
- Generics.Deriving.TH: deriveRep0WithKindSigs :: Name -> Q [Dec]
- Generics.Deriving.TH: deriveRep1WithKindSigs :: Name -> Q [Dec]
- Generics.Deriving.TH: deriveRepresentable0WithKindSigs :: Name -> Q [Dec]
- Generics.Deriving.TH: deriveRepresentable1WithKindSigs :: Name -> Q [Dec]
+ Generics.Deriving.TH: InlineRep :: RepOptions
+ Generics.Deriving.TH: Options :: RepOptions -> KindSigOptions -> Options
+ Generics.Deriving.TH: TypeSynonymRep :: RepOptions
+ Generics.Deriving.TH: [kindSigOptions] :: Options -> KindSigOptions
+ Generics.Deriving.TH: [repOptions] :: Options -> RepOptions
+ Generics.Deriving.TH: data Options
+ Generics.Deriving.TH: data RepOptions
+ Generics.Deriving.TH: defaultKindSigOptions :: KindSigOptions
+ Generics.Deriving.TH: defaultOptions :: Options
+ Generics.Deriving.TH: defaultRepOptions :: RepOptions
+ Generics.Deriving.TH: deriveAll0And1Options :: Options -> Name -> Q [Dec]
+ Generics.Deriving.TH: deriveAll0Options :: Options -> Name -> Q [Dec]
+ Generics.Deriving.TH: deriveAll1Options :: Options -> Name -> Q [Dec]
+ Generics.Deriving.TH: deriveRep0Options :: KindSigOptions -> Name -> Q [Dec]
+ Generics.Deriving.TH: deriveRep1Options :: KindSigOptions -> Name -> Q [Dec]
+ Generics.Deriving.TH: deriveRepresentable0Options :: Options -> Name -> Q [Dec]
+ Generics.Deriving.TH: deriveRepresentable1Options :: Options -> Name -> Q [Dec]
+ Generics.Deriving.TH: instance GHC.Classes.Eq Generics.Deriving.TH.Options
+ Generics.Deriving.TH: instance GHC.Classes.Eq Generics.Deriving.TH.RepOptions
+ Generics.Deriving.TH: instance GHC.Classes.Ord Generics.Deriving.TH.Options
+ Generics.Deriving.TH: instance GHC.Classes.Ord Generics.Deriving.TH.RepOptions
+ Generics.Deriving.TH: instance GHC.Read.Read Generics.Deriving.TH.Options
+ Generics.Deriving.TH: instance GHC.Read.Read Generics.Deriving.TH.RepOptions
+ Generics.Deriving.TH: instance GHC.Show.Show Generics.Deriving.TH.Options
+ Generics.Deriving.TH: instance GHC.Show.Show Generics.Deriving.TH.RepOptions
+ Generics.Deriving.TH: makeRep0Inline :: Name -> Q Type -> Q Type
+ Generics.Deriving.TH: makeRep1Inline :: Name -> Q Type -> Q Type
+ Generics.Deriving.TH: type KindSigOptions = Bool
Files
- CHANGELOG.md +43/−0
- generic-deriving.cabal +2/−2
- src/Generics/Deriving/Base/Internal.hs +1/−1
- src/Generics/Deriving/TH.hs +394/−207
- src/Generics/Deriving/TH/Internal.hs +93/−64
CHANGELOG.md view
@@ -1,3 +1,46 @@+# 1.11+* The behavior of function in `Generics.Deriving.TH` has changed with respect+ to when type synonyms are generated for `Rep(1)` definitions. In particular:++ * By default, `deriveRepresentable(1)` will no longer define its `Rep(1)`+ type family instance in terms of the type synonym that has to be generated+ with `deriveRep(1)`. Similarly, `deriveAll(1)` and `deriveAll0And1` will no+ longer generate a type synonym. Instead, they will generate `Generic(1)`+ instances that directly define the `Rep(1)` instance inline. If you wish+ to revert to the old behavior, you will need to use the variants of those+ functions suffixed with `-Options`.+ * New functions `makeRep0Inline` and `makeRep1Inline` have been added which,+ for most purposes, should replace uses of `makeRep0`/`makeRep0FromType`+ and `makeRep1`/`makeRep1FromType` (but see the next bullet point for a+ caveat).+ * The use of `deriveRep(1)`, `makeRep0`/`makeRep0FromType`, and+ `makeRep1`/`makeRep1FromType` are now discouraged, but those functions are+ still available. The reason is that on GHC 7.0/7.2/7.4, it is impossible to use+ `makeRep0Inline`/`makeRep1Inline` due to a GHC bug. Therefore, you must use+ `makeRep0`/`makeRep1` and `deriveRep(1)` on GHC 7.0/7.2/7.4 out of necessity.++ These changes make dealing with `Generic` instances that involve `PolyKinds`+ and `TypeInType` much easier.+* All functions suffixed in `-WithKindSigs` in `Generics.Deriving.TH` have been+ removed in favor of a more sensible `-Options` suffixing scheme. The ability to+ toggle whether explicit kind signatures are used on type variable binders has+ been folded into `KindSigOptions`, which is an explicit argument to+ `deriveRep0Options`/`deriveRep1Options` and also a field in the more general+ 'Options' data type.+* Furthermore, the behavior of derived instances' kind signatures has changed.+ By default, the TH code will now _always_ use explicit kind signatures+ whenever possible, regardless of whether you're working with plain data types+ or data family instances. This makes working with `TypeInType` less+ surprising, but at the cost of making it slightly more awkward to work with+ derived `Generic1` instances that constrain kinds to `*` by means of `(:.:)`.+* Since `Generic1` is polykinded on GHC 8.2 and later, the functions in+ `Generics.Deriving.TH` will no longer unify the kind of the last type+ parameter to be `*`.+* Fix a bug in which `makeRep` (and similarly named functions) would not check+ whether the argument type can actually have a well kinded `Generic(1)`+ instance.+* Backport missing `Foldable` and `Traversable` instances for `Rec1`+ # 1.10.7 * Renamed internal modules to avoid using apostrophes (averting this bug: https://github.com/haskell/cabal/issues/3631)
generic-deriving.cabal view
@@ -1,5 +1,5 @@ name: generic-deriving-version: 1.10.7+version: 1.11 synopsis: Generic programming library for generalised deriving. description: @@ -12,7 +12,7 @@ . The current implementation integrates with the new GHC Generics. See <http://www.haskell.org/haskellwiki/GHC.Generics> for more information.- Template Haskell code is provided for supporting GHC before version 7.2.+ Template Haskell code is provided for supporting older GHCs. homepage: https://github.com/dreixel/generic-deriving bug-reports: https://github.com/dreixel/generic-deriving/issues
src/Generics/Deriving/Base/Internal.hs view
@@ -729,7 +729,7 @@ -- | Recursive calls of kind * -> * newtype Rec1 f p = Rec1 { unRec1 :: f p }- deriving (Eq, Ord, Read, Functor, Show)+ deriving (Eq, Ord, Read, Functor, Foldable, Traversable, Show) instance Applicative f => Applicative (Rec1 f) where pure a = Rec1 (pure a)
src/Generics/Deriving/TH.hs view
@@ -43,7 +43,7 @@ -- Adapted from Generics.Regular.TH module Generics.Deriving.TH (-+ -- * @derive@- functions deriveMeta , deriveData , deriveConstructors@@ -58,27 +58,40 @@ , deriveRep0 , deriveRep1 , simplInstance- -- * -@WithSigs@ functions- -- $withSigs- , deriveAll0WithKindSigs- , deriveAll1WithKindSigs- , deriveAll0And1WithKindSigs- , deriveRepresentable0WithKindSigs- , deriveRepresentable1WithKindSigs- , deriveRep0WithKindSigs- , deriveRep1WithKindSigs+ -- * @make@- functions -- $make+ , makeRep0Inline , makeRep0 , makeRep0FromType , makeFrom , makeFrom0 , makeTo , makeTo0+ , makeRep1Inline , makeRep1 , makeRep1FromType , makeFrom1 , makeTo1++ -- * Options+ -- $options+ -- ** Option types+ , Options(..)+ , defaultOptions+ , RepOptions(..)+ , defaultRepOptions+ , KindSigOptions+ , defaultKindSigOptions++ -- ** Functions with optional arguments+ , deriveAll0Options+ , deriveAll1Options+ , deriveAll0And1Options+ , deriveRepresentable0Options+ , deriveRepresentable1Options+ , deriveRep0Options+ , deriveRep1Options ) where import Control.Monad ((>=>), unless, when)@@ -88,6 +101,7 @@ #endif import Data.List (nub) import qualified Data.Map as Map (fromList)+import Data.Maybe (catMaybes) import Generics.Deriving.TH.Internal #if MIN_VERSION_base(4,9,0)@@ -99,33 +113,26 @@ import Language.Haskell.TH.Lib import Language.Haskell.TH -{- $withSigs-By default, 'deriveRep0', 'deriveRep1', and functions that invoke it generate-type synonyms whose type variable binders do not have explicit kind binders for-polykinded type variables. This is a pretty reasonable default, since puts less-of a burden on the Template Haskell machinery to get the kinds just right, and-lets the kind inferencer do more work. However, there are times when you want to-have explicit kind signatures, such as if you have a datatype that uses-@-XTypeInType@. For example:--@-data Prox (a :: k) (b :: *) = Prox k-$('deriveRep0WithKindSigs' ''Prox)-@--will result in something like:--@-type Rep0Prox (a :: k) (b :: *) = Rec0 k-@+{- $options+'Options' gives you a way to further tweak derived 'Generic' and 'Generic1' instances: -Whereas if you had used 'deriveRep0', you would have something like:+* 'RepOptions': By default, all derived 'Rep' and 'Rep1' type instances emit the code+ directly (the 'InlineRep' option). One can also choose to emit a separate type+ synonym for the 'Rep' type (this is the functionality of 'deriveRep0' and+ 'deriveRep1') and define a 'Rep' instance in terms of that type synonym (the+ 'TypeSynonymRep' option). -@-type Rep0Prox a (b :: *) = Rec0 k-@+* 'KindSigOptions': By default, all derived instances will use explicit kind+ signatures (when the 'KindSigOptions' is 'True'). You might wish to set the+ 'KindSigOptions' to 'False' if you want a 'Generic'/'Generic1' instance at+ a particular kind that GHC will infer correctly, but the functions in this+ module won't guess correctly. For example, the following example will only+ compile with 'KindSigOptions' set to 'False': -which will fail to compile, since k is out-of-scope!+ @+ newtype Compose (f :: k2 -> *) (g :: k1 -> k2) (a :: k1) = Compose (f (g a))+ $('deriveAll1Options' False ''Compose)+ @ -} -- | Given the names of a generic class, a type to instantiate, a function in@@ -140,6 +147,39 @@ [funD fn [clause [] (normalB (varE df `appE` (sigE (varE undefinedValName) (return typ)))) []]] +-- | Additional options for configuring derived 'Generic'/'Generic1' instances+-- using Template Haskell.+data Options = Options+ { repOptions :: RepOptions+ , kindSigOptions :: KindSigOptions+ } deriving (Eq, Ord, Read, Show)++-- | Sensible default 'Options' ('defaultRepOptions' and 'defaultKindSigOptions').+defaultOptions :: Options+defaultOptions = Options+ { repOptions = defaultRepOptions+ , kindSigOptions = defaultKindSigOptions+ }++-- | Configures whether 'Rep'/'Rep1' type instances should be defined inline in a+-- derived 'Generic'/'Generic1' instance ('InlineRep') or defined in terms of a+-- type synonym ('TypeSynonymRep').+data RepOptions = InlineRep+ | TypeSynonymRep+ deriving (Eq, Ord, Read, Show)++-- | 'InlineRep', a sensible default 'RepOptions'.+defaultRepOptions :: RepOptions+defaultRepOptions = InlineRep++-- | 'True' if explicit kind signatures should be used in derived+-- 'Generic'/'Generic1' instances, 'False' otherwise.+type KindSigOptions = Bool++-- | 'True', a sensible default 'KindSigOptions'.+defaultKindSigOptions :: KindSigOptions+defaultKindSigOptions = True+ -- | A backwards-compatible synonym for 'deriveAll0'. deriveAll :: Name -> Q [Dec] deriveAll = deriveAll0@@ -148,134 +188,133 @@ -- generate the 'Data' instance, the 'Constructor' instances, the 'Selector' -- instances, and the 'Representable0' instance. deriveAll0 :: Name -> Q [Dec]-deriveAll0 = deriveAllCommon True False False+deriveAll0 = deriveAll0Options defaultOptions --- | Like 'deriveAll0', except that the type variable binders in the--- 'Rep' type synonym will have explicit kind signatures.-deriveAll0WithKindSigs :: Name -> Q [Dec]-deriveAll0WithKindSigs = deriveAllCommon True False True+-- | Like 'deriveAll0', but takes an 'Options' argument.+deriveAll0Options :: Options -> Name -> Q [Dec]+deriveAll0Options = deriveAllCommon True False -- | Given the type and the name (as string) for the type to derive, -- generate the 'Data' instance, the 'Constructor' instances, the 'Selector' -- instances, and the 'Representable1' instance. deriveAll1 :: Name -> Q [Dec]-deriveAll1 = deriveAllCommon False True False+deriveAll1 = deriveAll1Options defaultOptions --- | Like 'deriveAll1', except that the type variable binders in the--- 'Rep1' type synonym will have explicit kind signatures.-deriveAll1WithKindSigs :: Name -> Q [Dec]-deriveAll1WithKindSigs = deriveAllCommon False True True+-- | Like 'deriveAll1', but takes an 'Options' argument.+deriveAll1Options :: Options -> Name -> Q [Dec]+deriveAll1Options = deriveAllCommon False True -- | Given the type and the name (as string) for the type to derive, -- generate the 'Data' instance, the 'Constructor' instances, the 'Selector' -- instances, the 'Representable0' instance, and the 'Representable1' instance. deriveAll0And1 :: Name -> Q [Dec]-deriveAll0And1 = deriveAllCommon True True False+deriveAll0And1 = deriveAll0And1Options defaultOptions --- | Like 'deriveAll0And1', except that the type variable binders in the--- 'Rep' and 'Rep1' type synonyms will have explicit kind signatures.-deriveAll0And1WithKindSigs :: Name -> Q [Dec]-deriveAll0And1WithKindSigs = deriveAllCommon True True True+-- | Like 'deriveAll0And1', but takes an 'Options' argument.+deriveAll0And1Options :: Options -> Name -> Q [Dec]+deriveAll0And1Options = deriveAllCommon True True -deriveAllCommon :: Bool -> Bool -> Bool -> Name -> Q [Dec]-deriveAllCommon generic generic1 useKindSigs n = do+deriveAllCommon :: Bool -> Bool -> Options -> Name -> Q [Dec]+deriveAllCommon generic generic1 opts n = do a <- deriveMeta n b <- if generic- then deriveRepresentableCommon Generic useKindSigs n+ then deriveRepresentableCommon Generic opts n else return [] c <- if generic1- then deriveRepresentableCommon Generic1 useKindSigs n+ then deriveRepresentableCommon Generic1 opts n else return [] return (a ++ b ++ c) -- | Given the type and the name (as string) for the Representable0 type -- synonym to derive, generate the 'Representable0' instance. deriveRepresentable0 :: Name -> Q [Dec]-deriveRepresentable0 = deriveRepresentableCommon Generic False+deriveRepresentable0 = deriveRepresentable0Options defaultOptions --- | Like 'deriveRepresentable0', except that the type variable binders in the--- 'Rep' type synonym will have explicit kind signatures.-deriveRepresentable0WithKindSigs :: Name -> Q [Dec]-deriveRepresentable0WithKindSigs = deriveRepresentableCommon Generic True+-- | Like 'deriveRepresentable0', but takes an 'Options' argument.+deriveRepresentable0Options :: Options -> Name -> Q [Dec]+deriveRepresentable0Options = deriveRepresentableCommon Generic -- | Given the type and the name (as string) for the Representable1 type -- synonym to derive, generate the 'Representable1' instance. deriveRepresentable1 :: Name -> Q [Dec]-deriveRepresentable1 = deriveRepresentableCommon Generic1 False+deriveRepresentable1 = deriveRepresentable1Options defaultOptions --- | Like 'deriveRepresentable1', except that the type variable binders in the--- 'Rep1' type synonym will have explicit kind signatures.-deriveRepresentable1WithKindSigs :: Name -> Q [Dec]-deriveRepresentable1WithKindSigs = deriveRepresentableCommon Generic1 True+-- | Like 'deriveRepresentable1', but takes an 'Options' argument.+deriveRepresentable1Options :: Options -> Name -> Q [Dec]+deriveRepresentable1Options = deriveRepresentableCommon Generic1 -deriveRepresentableCommon :: GenericClass -> Bool -> Name -> Q [Dec]-deriveRepresentableCommon gClass useKindSigs n = do- rep <- deriveRepCommon gClass useKindSigs n- inst <- deriveInst gClass n+deriveRepresentableCommon :: GenericClass -> Options -> Name -> Q [Dec]+deriveRepresentableCommon gClass opts n = do+ rep <- if repOptions opts == InlineRep+ then return []+ else deriveRepCommon gClass (kindSigOptions opts) n+ inst <- deriveInst gClass opts n return (rep ++ inst) -- | Derive only the 'Rep0' type synonym. Not needed if 'deriveRepresentable0' -- is used. deriveRep0 :: Name -> Q [Dec]-deriveRep0 = deriveRepCommon Generic False+deriveRep0 = deriveRep0Options defaultKindSigOptions --- | Like 'deriveRep0', except that the type variable binders in the 'Rep'--- type synonym will have explicit kind signatures.-deriveRep0WithKindSigs :: Name -> Q [Dec]-deriveRep0WithKindSigs = deriveRepCommon Generic True+-- | Like 'deriveRep0', but takes an 'KindSigOptions' argument.+deriveRep0Options :: KindSigOptions -> Name -> Q [Dec]+deriveRep0Options = deriveRepCommon Generic -- | Derive only the 'Rep1' type synonym. Not needed if 'deriveRepresentable1' -- is used. deriveRep1 :: Name -> Q [Dec]-deriveRep1 = deriveRepCommon Generic1 False+deriveRep1 = deriveRep1Options defaultKindSigOptions --- | Like 'deriveRep1', except that the type variable binders in the 'Rep1'--- type synonym will have explicit kind signatures.-deriveRep1WithKindSigs :: Name -> Q [Dec]-deriveRep1WithKindSigs = deriveRepCommon Generic1 True+-- | Like 'deriveRep1', but takes an 'KindSigOptions' argument.+deriveRep1Options :: KindSigOptions -> Name -> Q [Dec]+deriveRep1Options = deriveRepCommon Generic1 -deriveRepCommon :: GenericClass -> Bool -> Name -> Q [Dec]+deriveRepCommon :: GenericClass -> KindSigOptions -> Name -> Q [Dec] deriveRepCommon gClass useKindSigs n = do i <- reifyDataInfo n let (name, isNT, declTvbs, cons, dv) = either error id i -- See Note [Forcing buildTypeInstance]- !_ <- buildTypeInstance gClass name declTvbs dv+ !_ <- buildTypeInstance gClass useKindSigs name declTvbs dv+ tySynVars <- grabTyVarsFromCons gClass cons - tySynTvbs <- grabTyVarBndrsFromCons gClass cons- let tySynTvbs' = if useKindSigs- then tySynTvbs- else map (\tvb -> if isKindMonomorphic (tyVarBndrKind tvb)- then tvb- else unKindedTV tvb) tySynTvbs+ -- See Note [Kind signatures in derived instances]+ let tySynVars' = if useKindSigs+ then tySynVars+ else map unSigT tySynVars fmap (:[]) $ tySynD (genRepName gClass dv name)- tySynTvbs'- -- The typechecker will infer the kinds of the TyVarBndrs- -- in a type synonym declaration, so we don't need to- -- splice them in explicitly (hence the unKindedTV call).- (repType gClass dv name isNT cons tySynTvbs)+ (catMaybes $ map typeToTyVarBndr tySynVars')+ (repType gClass dv name isNT cons tySynVars) -deriveInst :: GenericClass -> Name -> Q [Dec]+deriveInst :: GenericClass -> Options -> Name -> Q [Dec] deriveInst Generic = deriveInstCommon genericTypeName repTypeName Generic fromValName toValName deriveInst Generic1 = deriveInstCommon generic1TypeName rep1TypeName Generic1 from1ValName to1ValName -deriveInstCommon :: Name -> Name -> GenericClass -> Name -> Name -> Name -> Q [Dec]-deriveInstCommon genericName repName gClass fromName toName n = do+deriveInstCommon :: Name -> Name -> GenericClass -> Name -> Name -> Options -> Name -> Q [Dec]+deriveInstCommon genericName repName gClass fromName toName opts n = do i <- reifyDataInfo n- let (name, _, allTvbs, cons, dv) = either error id i- origTy <- buildTypeInstance gClass name allTvbs dv- repTySynApp <- makeRepTySynApp gClass dv name cons origTy- let tyIns = TySynInstD repName+ let (name, isNT, allTvbs, cons, dv) = either error id i+ useKindSigs = kindSigOptions opts+ -- See Note [Forcing buildTypeInstance]+ !(origTy, origKind) <- buildTypeInstance gClass useKindSigs name allTvbs dv+ tyInsRHS <- if repOptions opts == InlineRep+ then makeRepInline gClass dv name isNT cons origTy+ else makeRepTySynApp gClass dv name cons origTy++ let origSigTy = if useKindSigs+ then SigT origTy origKind+ else origTy+ tyIns = TySynInstD repName #if MIN_VERSION_template_haskell(2,9,0)- (TySynEqn [origTy] repTySynApp)+ (TySynEqn [origSigTy] tyInsRHS) #else- [origTy] repTySynApp+ [origSigTy] tyInsRHS #endif mkBody maker = [clause [] (normalB $ mkCaseExp gClass name cons maker) []] fcs = mkBody mkFrom tcs = mkBody mkTo fmap (:[]) $- instanceD (cxt []) (conT genericName `appT` return origTy)+ instanceD (cxt []) (conT genericName `appT` return origSigTy) [return tyIns, funD fromName fcs, funD toName tcs] {- $make@@ -285,7 +324,7 @@ 'Generic1' instances. As an example, consider this data type: @-data Fix f a = Fix (f (Fix f a))+newtype Fix f a = Fix (f (Fix f a)) @ A proper 'Generic1' instance would look like this:@@ -302,16 +341,16 @@ $('deriveMeta' ''Fix) $('deriveRep1' ''Fix) instance Functor f => Generic1 (Fix f) where- type Rep1 (Fix f) = $('makeRep1FromType' ''Fix [t| Fix f |])+ type Rep1 (Fix f) = $('makeRep1Inline' ''Fix [t| Fix f |]) from1 = $('makeFrom1' ''Fix) to1 = $('makeTo1' ''Fix) @ Note that due to the lack of type-level lambdas in Haskell, one must manually-apply @'makeRep1FromType' ''Fix@ to the type @Fix f@.+apply @'makeRep1Inline' ''Fix@ to the type @Fix f@. Be aware that there is a bug on GHC 7.0, 7.2, and 7.4 which might prevent you from-using 'makeRep0FromType' and 'makeRep1FromType'. In the @Fix@ example above, you+using 'makeRep0Inline' and 'makeRep1Inline'. In the @Fix@ example above, you would experience the following error: @@@ -319,11 +358,16 @@ In the Template Haskell quotation [t| Fix f |] @ -Then a workaround is to use 'makeRep1' instead, which requires you to pass as-arguments the type variables that occur in the instance, in order from left to-right, excluding duplicates. (Normally, 'makeRep1FromType' would figure this-out for you.) Using the above example:+Then a workaround is to use 'makeRep1' instead, which requires you to: +1. Invoke 'deriveRep1' beforehand++2. Pass as arguments the type variables that occur in the instance, in order+ from left to right, topologically sorted, excluding duplicates. (Normally,+ 'makeRep1Inline' would figure this out for you.)++Using the above example:+ @ $('deriveMeta' ''Fix) $('deriveRep1' ''Fix)@@ -351,6 +395,40 @@ Note that you don't pass @b@ twice, only once. -} +-- | Generates the full 'Rep' type inline. Since this type can be quite+-- large, it is recommended you only use this to define 'Rep', e.g.,+--+-- @+-- type Rep (Foo (a :: k) b) = $('makeRep0Inline' ''Foo [t| Foo (a :: k) b |])+-- @+--+-- You can then simply refer to @Rep (Foo a b)@ elsewhere.+--+-- Note that the type passed as an argument to 'makeRep0Inline' must match the+-- type argument of 'Rep' exactly, even up to including the explicit kind+-- signature on @a@. This is due to a limitation of Template Haskell—without+-- the kind signature, 'makeRep0Inline' has no way of figuring out the kind of+-- @a@, and the generated type might be completely wrong as a result!+makeRep0Inline :: Name -> Q Type -> Q Type+makeRep0Inline n = makeRepCommon Generic InlineRep n . Just++-- | Generates the full 'Rep1' type inline. Since this type can be quite+-- large, it is recommended you only use this to define 'Rep1', e.g.,+--+-- @+-- type Rep1 (Foo (a :: k)) = $('makeRep0Inline' ''Foo [t| Foo (a :: k) |])+-- @+--+-- You can then simply refer to @Rep1 (Foo a)@ elsewhere.+--+-- Note that the type passed as an argument to 'makeRep1Inline' must match the+-- type argument of 'Rep1' exactly, even up to including the explicit kind+-- signature on @a@. This is due to a limitation of Template Haskell—without+-- the kind signature, 'makeRep1Inline' has no way of figuring out the kind of+-- @a@, and the generated type might be completely wrong as a result!+makeRep1Inline :: Name -> Q Type -> Q Type+makeRep1Inline n = makeRepCommon Generic1 InlineRep n . Just+ -- | Generates the 'Rep' type synonym constructor (as opposed to 'deriveRep0', -- which generates the type synonym declaration). After splicing it into -- Haskell source, it expects types as arguments. For example:@@ -358,52 +436,99 @@ -- @ -- type Rep (Foo a b) = $('makeRep0' ''Foo) a b -- @+--+-- The use of 'makeRep0' is generally discouraged, as it can sometimes be+-- difficult to predict the order in which you are expected to pass type+-- variables. As a result, 'makeRep0Inline' is recommended instead. However,+-- 'makeRep0Inline' is not usable on GHC 7.0, 7.2, or 7.4 due to a GHC bug,+-- so 'makeRep0' still exists for GHC 7.0, 7.2, and 7.4 users. makeRep0 :: Name -> Q Type-makeRep0 n = makeRepCommon Generic n Nothing+makeRep0 n = makeRepCommon Generic TypeSynonymRep n Nothing -- | Generates the 'Rep1' type synonym constructor (as opposed to 'deriveRep1', -- which generates the type synonym declaration). After splicing it into -- Haskell source, it expects types as arguments. For example: -- -- @--- type Rep1 (Foo a b) = $('makeRep1' ''Foo) a b+-- type Rep1 (Foo a) = $('makeRep1' ''Foo) a -- @+--+-- The use of 'makeRep1' is generally discouraged, as it can sometimes be+-- difficult to predict the order in which you are expected to pass type+-- variables. As a result, 'makeRep1Inline' is recommended instead. However,+-- 'makeRep1Inline' is not usable on GHC 7.0, 7.2, or 7.4 due to a GHC bug,+-- so 'makeRep1' still exists for GHC 7.0, 7.2, and 7.4 users. makeRep1 :: Name -> Q Type-makeRep1 n = makeRepCommon Generic1 n Nothing+makeRep1 n = makeRepCommon Generic1 TypeSynonymRep n Nothing -- | Generates the 'Rep' type synonym constructor (as opposed to 'deriveRep0', -- which generates the type synonym declaration) applied to its type arguments. -- Unlike 'makeRep0', this also takes a quoted 'Type' as an argument, e.g., -- -- @--- type Rep (Foo a b) = $('makeRep0FromType' ''Foo [t| Foo a b |])+-- type Rep (Foo (a :: k) b) = $('makeRep0FromType' ''Foo [t| Foo (a :: k) b |]) -- @+--+-- Note that the type passed as an argument to 'makeRep0FromType' must match the+-- type argument of 'Rep' exactly, even up to including the explicit kind+-- signature on @a@. This is due to a limitation of Template Haskell—without+-- the kind signature, 'makeRep0FromType' has no way of figuring out the kind of+-- @a@, and the generated type might be completely wrong as a result!+--+-- The use of 'makeRep0FromType' is generally discouraged, since 'makeRep0Inline'+-- does exactly the same thing but without having to go through an intermediate+-- type synonym, and as a result, 'makeRep0Inline' tends to be less buggy. makeRep0FromType :: Name -> Q Type -> Q Type-makeRep0FromType n = makeRepCommon Generic n . Just+makeRep0FromType n = makeRepCommon Generic TypeSynonymRep n . Just -- | Generates the 'Rep1' type synonym constructor (as opposed to 'deriveRep1', -- which generates the type synonym declaration) applied to its type arguments. -- Unlike 'makeRep1', this also takes a quoted 'Type' as an argument, e.g., -- -- @--- type Rep1 (Foo a b) = $('makeRep1FromType' ''Foo [t| Foo a b |])+-- type Rep1 (Foo (a :: k)) = $('makeRep1FromType' ''Foo [t| Foo (a :: k) |]) -- @+--+-- Note that the type passed as an argument to 'makeRep1FromType' must match the+-- type argument of 'Rep' exactly, even up to including the explicit kind+-- signature on @a@. This is due to a limitation of Template Haskell—without+-- the kind signature, 'makeRep1FromType' has no way of figuring out the kind of+-- @a@, and the generated type might be completely wrong as a result!+--+-- The use of 'makeRep1FromType' is generally discouraged, since 'makeRep1Inline'+-- does exactly the same thing but without having to go through an intermediate+-- type synonym, and as a result, 'makeRep1Inline' tends to be less buggy. makeRep1FromType :: Name -> Q Type -> Q Type-makeRep1FromType n = makeRepCommon Generic1 n . Just+makeRep1FromType n = makeRepCommon Generic1 TypeSynonymRep n . Just makeRepCommon :: GenericClass+ -> RepOptions -> Name -> Maybe (Q Type) -> Q Type-makeRepCommon gClass n mbQTy = do+makeRepCommon gClass repOpts n mbQTy = do i <- reifyDataInfo n- let (name, _, _, cons, dv) = either error id i- case mbQTy of- Just qTy -> do- ty <- qTy- makeRepTySynApp gClass dv name cons ty- Nothing -> conT $ genRepName gClass dv name+ let (name, isNT, declTvbs, cons, dv) = either error id i+ -- See Note [Forcing buildTypeInstance]+ !_ <- buildTypeInstance gClass False name declTvbs dv + case (mbQTy, repOpts) of+ (Just qTy, TypeSynonymRep) -> qTy >>= makeRepTySynApp gClass dv name cons+ (Just qTy, InlineRep) -> qTy >>= makeRepInline gClass dv name isNT cons+ (Nothing, TypeSynonymRep) -> conT $ genRepName gClass dv name+ (Nothing, InlineRep) -> fail "makeRepCommon"++makeRepInline :: GenericClass+ -> DataVariety+ -> Name+ -> Bool+ -> [Con]+ -> Type+ -> Q Type+makeRepInline gClass dv name isNT cons ty = do+ let instVars = map tyVarBndrToType $ tyVarsOfType ty+ repType gClass dv name isNT cons instVars+ makeRepTySynApp :: GenericClass -> DataVariety -> Name@@ -415,15 +540,15 @@ -- of the LHS of the Rep(1) instance. We call unKindedTV because the kind -- inferencer can figure out the kinds perfectly well, so we don't need to -- give anything here explicit kind signatures.- let instTvbs = nub . map unKindedTV $ visibleTyVarsOfType ty+ let instTvbs = nub . map unKindedTV $ requiredTyVarsOfType ty -- We grab the type variables from the first constructor's type signature. -- Or, if there are no constructors, we grab no type variables. The latter -- is okay because we use zipWith to ensure that we never pass more type -- variables than the generated type synonym can accept. -- See Note [Arguments to generated type synonyms]- tySynTvbs <- grabTyVarBndrsFromCons gClass cons+ tySynVars <- grabTyVarsFromCons gClass cons return . applyTyToTvbs (genRepName gClass dv name)- $ zipWith const instTvbs tySynTvbs+ $ zipWith const instTvbs tySynVars -- | A backwards-compatible synonym for 'makeFrom0'. makeFrom :: Name -> Q Exp@@ -455,7 +580,7 @@ i <- reifyDataInfo n let (name, _, allTvbs, cons, dv) = either error id i -- See Note [Forcing buildTypeInstance]- buildTypeInstance gClass name allTvbs dv+ buildTypeInstance gClass False name allTvbs dv `seq` mkCaseExp gClass name cons maker genRepName :: GenericClass -> DataVariety -> Name -> Name@@ -471,12 +596,12 @@ -> Name -> Bool -> [Con]- -> [TyVarBndr]+ -> [Type] -> Q Type-repType gClass dv dt isNT cs tySynTvbs =+repType gClass dv dt isNT cs tySynVars = conT d1TypeName `appT` mkMetaDataType dv dt isNT `appT` foldr1' sum' (conT v1TypeName)- (map (repCon gClass dv dt tySynTvbs) cs)+ (map (repCon gClass dv dt tySynVars) cs) where sum' :: Q Type -> Q Type -> Q Type sum' a b = conT sumTypeName `appT` a `appT` b@@ -484,35 +609,35 @@ repCon :: GenericClass -> DataVariety -> Name- -> [TyVarBndr]+ -> [Type] -> Con -> Q Type-repCon gClass dv dt tySynTvbs (NormalC n bts) = do+repCon gClass dv dt tySynVars (NormalC n bts) = do let bangs = map fst bts ssis <- reifySelStrictInfo n bangs- repConWith gClass dv dt n tySynTvbs Nothing ssis False False-repCon gClass dv dt tySynTvbs (RecC n vbts) = do+ repConWith gClass dv dt n tySynVars Nothing ssis False False+repCon gClass dv dt tySynVars (RecC n vbts) = do let (selNames, bangs, _) = unzip3 vbts ssis <- reifySelStrictInfo n bangs- repConWith gClass dv dt n tySynTvbs (Just selNames) ssis True False-repCon gClass dv dt tySynTvbs (InfixC t1 n t2) = do+ repConWith gClass dv dt n tySynVars (Just selNames) ssis True False+repCon gClass dv dt tySynVars (InfixC t1 n t2) = do let bangs = map fst [t1, t2] ssis <- reifySelStrictInfo n bangs- repConWith gClass dv dt n tySynTvbs Nothing ssis False True+ repConWith gClass dv dt n tySynVars Nothing ssis False True repCon _ _ _ _ con = gadtError con repConWith :: GenericClass -> DataVariety -> Name -> Name- -> [TyVarBndr]+ -> [Type] -> Maybe [Name] -> [SelStrictInfo] -> Bool -> Bool -> Q Type-repConWith gClass dv dt n tySynTvbs mbSelNames ssis isRecord isInfix = do- (conTvbs, ts, gk) <- reifyConTys gClass n+repConWith gClass dv dt n tySynVars mbSelNames ssis isRecord isInfix = do+ (conVars, ts, gk) <- reifyConTys gClass n let structureType :: Q Type structureType = case ssis of@@ -522,8 +647,8 @@ -- See Note [Substituting types in a constructor type signature] typeSubst :: TypeSubst typeSubst = Map.fromList $- zip (concatMap tyVarNamesOfTyVarBndr conTvbs)- (concatMap (map VarT . tyVarNamesOfTyVarBndr) tySynTvbs)+ zip (concatMap tyVarNamesOfType conVars)+ (concatMap (map VarT . tyVarNamesOfType) tySynVars) f :: [Q Type] f = case mbSelNames of@@ -556,7 +681,13 @@ -- See Note [Substituting types in constructor type signatures] t', t'' :: Type t' = case gk of- Gen1 _ (Just kvName) -> substNameWithKind kvName starK t+ Gen1 _ (Just _kvName) ->+-- See Note [Generic1 is polykinded on GHC 8.2]+#if __GLASGOW_HASKELL__ >= 801+ t+#else+ substNameWithKind _kvName starK t+#endif _ -> t t'' = substType typeSubst t' @@ -805,9 +936,11 @@ | ty == ConT wordHashTypeName = Just (uWordTypeName, uWordDataName, uWordHashValName) | otherwise = Nothing --- | Deduces the instance type to use for a Generic(1) instance.+-- | Deduces the instance type (and kind) to use for a Generic(1) instance. buildTypeInstance :: GenericClass -- ^ Generic or Generic1+ -> KindSigOptions+ -- ^ Whether or not to use explicit kind signatures in the instance type -> Name -- ^ The type constructor or data family name -> [TyVarBndr]@@ -815,17 +948,17 @@ -> DataVariety -- ^ If using a data family instance, provides the types used -- to instantiate the instance- -> Q Type+ -> Q (Type, Kind) -- Plain data type/newtype case-buildTypeInstance gClass tyConName tvbs DataPlain =+buildTypeInstance gClass useKindSigs tyConName tvbs DataPlain = let varTys :: [Type] varTys = map tyVarBndrToType tvbs- in buildTypeInstanceFromTys gClass tyConName varTys False+ in buildTypeInstanceFromTys gClass useKindSigs tyConName varTys -- Data family instance case -- -- The CPP is present to work around a couple of annoying old GHC bugs. -- See Note [Polykinded data families in Template Haskell]-buildTypeInstance gClass parentName tvbs (DataFamily _ instTysAndKinds) = do+buildTypeInstance gClass useKindSigs parentName tvbs (DataFamily _ instTysAndKinds) = do #if !(MIN_VERSION_template_haskell(2,8,0)) || MIN_VERSION_template_haskell(2,10,0) let instTys :: [Type] instTys = zipWith stealKindForType tvbs instTysAndKinds@@ -860,11 +993,11 @@ xTypeNames <- newNameList "tExtra" (length tvbs - length givenTys) let xTys :: [Type]+ -- Because these type variables were eta-reduced away, we can only+ -- determine their kind by using stealKindForType. Therefore, we mark+ -- them as VarT to ensure they will be given an explicit kind annotation+ -- (and so the kind inference machinery has the right information). xTys = map VarT xTypeNames- -- ^ Because these type variables were eta-reduced away, we can only- -- determine their kind by using stealKindForType. Therefore, we mark- -- them as VarT to ensure they will be given an explicit kind annotation- -- (and so the kind inference machinery has the right information). substNamesWithKinds :: [(Name, Kind)] -> Type -> Type substNamesWithKinds nks t = foldr' (uncurry substNameWithKind) t nks@@ -884,22 +1017,23 @@ -- grab the correct kind. $ zipWith stealKindForType tvbs (givenTys ++ xTys) #endif- buildTypeInstanceFromTys gClass parentName instTys True+ buildTypeInstanceFromTys gClass useKindSigs parentName instTys --- For the given Types, deduces the instance type to use for a Generic(1) instance.--- Coming up with the instance type isn't as simple as dropping the last types, as--- you need to be wary of kinds being instantiated with *.+-- For the given Types, deduces the instance type (and kind) to use for a+-- Generic(1) instance. Coming up with the instance type isn't as simple as+-- dropping the last types, as you need to be wary of kinds being instantiated+-- with *. -- See Note [Type inference in derived instances] buildTypeInstanceFromTys :: GenericClass -- ^ Generic or Generic1+ -> KindSigOptions+ -- ^ Whether or not to use explicit kind signatures in the instance type -> Name -- ^ The type constructor or data family name -> [Type] -- ^ The types to instantiate the instance with- -> Bool- -- ^ True if it's a data family, False otherwise- -> Q Type-buildTypeInstanceFromTys gClass tyConName varTysOrig isDataFamily = do+ -> Q (Type, Kind)+buildTypeInstanceFromTys gClass useKindSigs tyConName varTysOrig = do -- Make sure to expand through type/kind synonyms! Otherwise, the -- eta-reduction check might get tripped up over type variables in a -- synonym that are actually dropped.@@ -920,35 +1054,30 @@ when (remainingLength < 0 || any (== NotKindStar) droppedStarKindStati) $ derivingKindError tyConName - let droppedKindVarNames :: [Name]- droppedKindVarNames = catKindVarNames droppedStarKindStati- -- Substitute kind * for any dropped kind variables- varTysExpSubst :: [Type]+ let varTysExpSubst :: [Type]+-- See Note [Generic1 is polykinded on GHC 8.2]+#if __GLASGOW_HASKELL__ >= 801+ varTysExpSubst = varTysExp+#else varTysExpSubst = map (substNamesWithKindStar droppedKindVarNames) varTysExp - -- We must take care to avoid allowing Generic1 instances where a visible kind- -- binder is instantiated to * (which should only happen in the presence of- -- -XTypeInType). See the documentation for instantiationError for an example- -- of when this can occur.- --- -- A quick-and-dirty way to accomplish this is to check if the visible type- -- binders of the original type, and of the type post-synonym-expansion, are- -- both the same. If not, it's likely that one of the type binders was- -- instantiated to a specific type (likely *).- when (concatMap visibleTyVarsOfType varTysExp- /= concatMap visibleTyVarsOfType varTysExpSubst) $- instantiationError tyConName+ droppedKindVarNames :: [Name]+ droppedKindVarNames = catKindVarNames droppedStarKindStati+#endif let remainingTysExpSubst, droppedTysExpSubst :: [Type] (remainingTysExpSubst, droppedTysExpSubst) = splitAt remainingLength varTysExpSubst +-- See Note [Generic1 is polykinded on GHC 8.2]+#if __GLASGOW_HASKELL__ < 801 -- If any of the dropped types were polykinded, ensure that there are of -- kind * after substituting * for the dropped kind variables. If not, -- throw an error. unless (all hasKindStar droppedTysExpSubst) $ derivingKindError tyConName+#endif -- We now substitute all of the specialized-to-* kind variable names -- with *, but in the original types, not the synonym-expanded types. The reason@@ -966,32 +1095,45 @@ -- Not: -- -- instance C (Fam [Char])- let remainingTysOrigSubst :: [Type]- remainingTysOrigSubst =+ let varTysOrigSubst :: [Type]+ varTysOrigSubst =+-- See Note [Generic1 is polykinded on GHC 8.2]+#if __GLASGOW_HASKELL__ >= 801+ id+#else map (substNamesWithKindStar droppedKindVarNames)- $ take remainingLength varTysOrig+#endif+ $ varTysOrig + remainingTysOrigSubst, droppedTysOrigSubst :: [Type]+ (remainingTysOrigSubst, droppedTysOrigSubst) =+ splitAt remainingLength varTysOrigSubst+ remainingTysOrigSubst' :: [Type] -- See Note [Kind signatures in derived instances] for an explanation- -- of the isDataFamily check.+ -- of the useKindSigs check. remainingTysOrigSubst' =- if isDataFamily+ if useKindSigs then remainingTysOrigSubst else map unSigT remainingTysOrigSubst instanceType :: Type instanceType = applyTyToTys (ConT tyConName) remainingTysOrigSubst' + -- See Note [Kind signatures in derived instances]+ instanceKind :: Kind+ instanceKind = makeFunKind (map typeKind droppedTysOrigSubst) starK+ -- Ensure the dropped types can be safely eta-reduced. Otherwise, -- throw an error. unless (canEtaReduce remainingTysExpSubst droppedTysExpSubst) $ etaReductionError instanceType- return instanceType+ return (instanceType, instanceKind) -- See Note [Arguments to generated type synonyms]-grabTyVarBndrsFromCons :: GenericClass -> [Con] -> Q [TyVarBndr]-grabTyVarBndrsFromCons _ [] = return []-grabTyVarBndrsFromCons gClass (con:_) =+grabTyVarsFromCons :: GenericClass -> [Con] -> Q [Type]+grabTyVarsFromCons _ [] = return []+grabTyVarsFromCons gClass (con:_) = fmap fst3 $ reifyConTys gClass (constructorName con) {-@@ -1030,12 +1172,13 @@ corresponding type variables from the data declaration. There is another obscure case where we need to do a type subtitution. With--XTypeInType enabled, you might have something like this:+-XTypeInType enabled on GHC 8.0, you might have something like this: data Proxy (a :: k) (b :: k) = Proxy k deriving Generic1 Then k gets specialized to *, which means that k should NOT show up in the RHS of a Rep1 type instance! To avoid this, make sure to substitute k with *.+See also Note [Generic1 is polykinded on GHC 8.2]. Note [Arguments to generated type synonyms] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -1108,33 +1251,77 @@ Note [Kind signatures in derived instances] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -It is possible to put explicit kind signatures into the derived instances, e.g.,+We generally include explicit type signatures in derived instances. One reason for+doing so is that in the case of certain data family instances, not including kind+signatures can result in ambiguity. For example, consider the following two data+family instances that are distinguished by their kinds: - instance C a => C (Data (f :: * -> *)) where ...+ data family Fam (a :: k)+ data instance Fam (a :: * -> *)+ data instance Fam (a :: *) -But it is preferable to avoid this if possible. If we come up with an incorrect-kind signature (which is entirely possible, since our type inferencer is pretty-unsophisticated - see Note [Type inference in derived instances]), then GHC will-flat-out reject the instance, which is quite unfortunate.+If we dropped the kind signature for a in a derived instance for Fam a, then GHC+would have no way of knowing which instance we are talking about. -Plain old datatypes have the advantage that you can avoid using any kind signatures-at all in their instances. This is because a datatype declaration uses all type-variables, so the types that we use in a derived instance uniquely determine their-kinds. As long as we plug in the right types, the kind inferencer can do the rest-of the work. For this reason, we use unSigT to remove all kind signatures before-splicing in the instance context and head.+Another motivation for explicit kind signatures is the -XTypeInType extension.+With -XTypeInType, dropping kind signatures can completely change the meaning+of some data types. For example, there is a substantial difference between these+two data types: -Data family instances are trickier, since a data family can have two instances that-are distinguished by kind alone, e.g.,+ data T k (a :: k) = T k+ data T k a = T k - data family Fam (a :: k)- data instance Fam (a :: * -> *)- data instance Fam (a :: *)+In addition to using explicit kind signatures on type variables, we also put+explicit return kinds in the instance head, so generated instances will look+something like this: -If we dropped the kind signatures for C (Fam a), then GHC will have no way of-knowing which instance we are talking about. To avoid this scenario, we always-include explicit kind signatures in data family instances. There is a chance that-the inferred kind signatures will be incorrect, but if so, we can always fall back-on the make- functions.+ data S (a :: k) = S k+ instance Generic1 (S :: k -> *) where+ type Rep1 (S :: k -> *) = ... (Rec0 k) +Why do we do this? Imagine what the instance would be without the explicit return kind:++ instance Generic1 S where+ type Rep1 S = ... (Rec0 k)++This is an error, since the variable k is now out-of-scope!++Although explicit kind signatures are the right thing to do in most cases, there+are sadly some degenerate cases where this isn't true. Consider this example:++ newtype Compose (f :: k2 -> *) (g :: k1 -> k2) (a :: k1) = Compose (f (g a))++The Rep1 type instance in a Generic1 instance for Compose would involve the type+(f :.: Rec1 g), which forces (f :: * -> *). But this library doesn't have very+sophisticated kind inference machinery (other than what is mentioned in+Note [Substituting types in constructor type signatures]), so at the moment we+have no way of actually unifying k1 with *. So the naïve generated Generic1+instance would be:++ instance Generic1 (Compose (f :: k2 -> *) (g :: k1 -> k2)) where+ type Rep1 (Compose f g) = ... (f :.: Rec1 g)++This is wrong, since f's kind is overly generalized. To get around this issue,+there are variants of the TH functions that allow you to configure the KindSigOptions.+If KindSigOptions is set to False, then generated instances will not include+explicit kind signatures, leaving it up to GHC's kind inference machinery to+figure out the correct kinds.++Note [Generic1 is polykinded on GHC 8.2]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++Prior to GHC 8.2, Generic1 :: (* -> *) -> Constraint. This means that if a Generic1+instance is defined for a polykinded data type like so:++ data Proxy k (a :: k) = Proxy++Then k is unified with *, and this has an effect on the generated Generic1 instance:++ instance Generic1 (Proxy *) where ...++We must take great care to ensure that all occurrences of k are substituted with *,+or else the generated instance will be ill kinded.++On GHC 8.2 and later, Generic1 :: (k -> *) -> Constraint. This means we don't have+to do this kind unification anymore! Hooray! -}
src/Generics/Deriving/TH/Internal.hs view
@@ -105,16 +105,17 @@ substNamesWithKindStar :: [Name] -> Type -> Type substNamesWithKindStar ns t = foldr' (flip substNameWithKind starK) t ns -substTyVarBndrKind :: KindSubst -> TyVarBndr -> TyVarBndr-substTyVarBndrKind _subs (KindedTV n k) = KindedTV n $+substTyVarBndrType :: TypeSubst -> TyVarBndr -> Type+substTyVarBndrType subs = substType subs . tyVarBndrToType++substTyVarBndrKind :: KindSubst -> TyVarBndr -> Type #if MIN_VERSION_template_haskell(2,8,0)- substKind _subs k+substTyVarBndrKind = substTyVarBndrType #else- k+substTyVarBndrKind _ = tyVarBndrToType #endif-substTyVarBndrKind _ tvb = tvb -substNameWithKindStarInTyVarBndr :: Name -> TyVarBndr -> TyVarBndr+substNameWithKindStarInTyVarBndr :: Name -> TyVarBndr -> Type substNameWithKindStarInTyVarBndr n = substTyVarBndrKind (Map.singleton n starK) -------------------------------------------------------------------------------@@ -162,10 +163,6 @@ #endif hasKindStar _ = False -tyVarNamesOfTyVarBndr :: TyVarBndr -> [Name]-tyVarNamesOfTyVarBndr (PlainTV n) = [n]-tyVarNamesOfTyVarBndr (KindedTV n k) = n:kindVarNamesOfKind k- -- | Gets all of the type/kind variable names mentioned somewhere in a Type. tyVarNamesOfType :: Type -> [Name] tyVarNamesOfType = go@@ -179,19 +176,24 @@ go (VarT n) = [n] go _ = [] --- | Gets all of the kind variable names mentioned somewhere in a Kind.-kindVarNamesOfKind :: Kind -> [Name]+-- | Gets all of the type/kind variable binders mentioned in a Type.+tyVarsOfType :: Type -> [TyVarBndr]+tyVarsOfType = go+ where+ go :: Type -> [TyVarBndr]+ go (AppT t1 t2) = go t1 ++ go t2+ go (SigT t _k) = go t #if MIN_VERSION_template_haskell(2,8,0)-kindVarNamesOfKind = tyVarNamesOfType-#else-kindVarNamesOfKind _ = [] -- There are no kind variables+ ++ go _k #endif+ go (VarT n) = [PlainTV n]+ go _ = [] --- | Gets all of the specified type/kind variable names mentioned in a Type. In--- contrast to 'tyVarNamesOfType', 'visibleTyVarsOfType' does not go into kinds+-- | Gets all of the required type/kind variable binders mentioned in a Type. In+-- contrast to 'tyVarsOfType', 'requiredTyVarsOfType' does not go into kinds -- of 'SigT's.-visibleTyVarsOfType :: Type -> [TyVarBndr]-visibleTyVarsOfType = go+requiredTyVarsOfType :: Type -> [TyVarBndr]+requiredTyVarsOfType = go where go :: Type -> [TyVarBndr] go (AppT t1 t2) = go t1 ++ go t2@@ -199,6 +201,50 @@ go (VarT n) = [PlainTV n] go _ = [] +-- | Converts a VarT or a SigT into Just the corresponding TyVarBndr.+-- Converts other Types to Nothing.+typeToTyVarBndr :: Type -> Maybe TyVarBndr+typeToTyVarBndr (VarT n) = Just (PlainTV n)+typeToTyVarBndr (SigT (VarT n) k) = Just (KindedTV n k)+typeToTyVarBndr _ = Nothing++-- | If a Type is a SigT, returns its kind signature. Otherwise, return *.+typeKind :: Type -> Kind+typeKind (SigT _ k) = k+typeKind _ = starK++-- | Turns+--+-- @+-- [a, b] c+-- @+--+-- into+--+-- @+-- a -> b -> c+-- @+makeFunType :: [Type] -> Type -> Type+makeFunType argTys resTy = foldr' (AppT . AppT ArrowT) resTy argTys++-- | Turns+--+-- @+-- [k1, k2] k3+-- @+--+-- into+--+-- @+-- k1 -> k2 -> k3+-- @+makeFunKind :: [Kind] -> Kind -> Kind+#if MIN_VERSION_template_haskell(2,8,0)+makeFunKind = makeFunType+#else+makeFunKind argKinds resKind = foldr' ArrowK resKind argKinds+#endif+ -- | Is the given type a type family constructor (and not a data family constructor)? isTyFamily :: Type -> Q Bool isTyFamily (ConT n) = do@@ -357,14 +403,6 @@ go VarT{} = False go _ = True --- | Returns 'True' is a 'Kind' contains no kind variables.-isKindMonomorphic :: Kind -> Bool-#if MIN_VERSION_template_haskell(2,8,0)-isKindMonomorphic = isTypeMonomorphic-#else-isKindMonomorphic _ = True -- There are no kind variables-#endif- -- | Peel off a kind signature from a Type (if it has one). unSigT :: Type -> Type unSigT (SigT t _) = t@@ -456,11 +494,12 @@ data GenericKind = Gen0 | Gen1 Name (Maybe Name) --- Determines the universally quantified type variables, the types of a constructor's+-- Determines the universally quantified type variables (possibly after+-- substituting * in the case of Generic1), the types of a constructor's -- arguments, and the last type parameter name (if there is one). reifyConTys :: GenericClass -> Name- -> Q ([TyVarBndr], [Type], GenericKind)+ -> Q ([Type], [Type], GenericKind) reifyConTys gClass conName = do info <- reify conName let (tvbs, uncTy) = case info of@@ -479,43 +518,48 @@ -- -- which you'd only be able to tell was legal if you expand Constant a b to a! resTyExp <- expandSyn resTy- let numResTyVars = length . nub $ visibleTyVarsOfType resTyExp- -- ^ We need to grab a number of type variables from the constructor's+ let numResTyVars = length . nub $ requiredTyVarsOfType resTyExp+ -- We need to grab a number of types from the constructor's -- type signature to re-use for the Rep(1) type synonym's type variable -- binders. As it turns out, that number is equal to the number of distinct -- type variables which appear in the result type. --- -- We assume that the visible type variables all come last in the list+ -- We assume that the required types all come last in the list -- of forall'd type variables. I suppose nothing guarantees this, but -- this seems to always be the case via experimentation. Fingers crossed.- -- TODO: This doesn't work with -XTypeInType and data families- visibleTvbs = drop (length tvbs - numResTyVars) tvbs- let (visibleTvbs', gk) = case gClass of- Generic -> (visibleTvbs, Gen0)+ requiredTvbs = drop (length tvbs - numResTyVars) tvbs+ let (requiredTyVars', gk) = case gClass of+ Generic -> (map tyVarBndrToType requiredTvbs, Gen0) Generic1 -> -- If deriving Generic1 and the last type variable is polykinded, -- make sure to substitute that kind with * in the other type -- variable binders' kind signatures- let headVisibleTvbs :: [TyVarBndr]- lastVisibleTvb :: TyVarBndr- (headVisibleTvbs, [lastVisibleTvb]) =- splitAt (length visibleTvbs - 1) visibleTvbs+ let headRequiredTvbs :: [TyVarBndr]+ lastRequiredTvb :: TyVarBndr+ (headRequiredTvbs, [lastRequiredTvb]) =+ splitAt (length requiredTvbs - 1) requiredTvbs mbLastArgKindName :: Maybe Name mbLastArgKindName = starKindStatusToName . canRealizeKindStar- $ tyVarBndrToType lastVisibleTvb+ $ tyVarBndrToType lastRequiredTvb - visibleTvbsSubst :: [TyVarBndr]- visibleTvbsSubst =+ requiredTyVars :: [Type]+ requiredTyVars = case mbLastArgKindName of- Nothing -> headVisibleTvbs- Just lakn -> map (substNameWithKindStarInTyVarBndr lakn)- headVisibleTvbs- in ( visibleTvbsSubst- , Gen1 (tyVarBndrName lastVisibleTvb) mbLastArgKindName+ Nothing -> map tyVarBndrToType headRequiredTvbs+ Just _lakn ->+-- See Note [Generic1 is polykinded on GHC 8.2] in Generics.Deriving.TH+#if __GLASGOW_HASKELL__ >= 801+ map tyVarBndrToType headRequiredTvbs+#else+ map (substNameWithKindStarInTyVarBndr _lakn)+ headRequiredTvbs+#endif+ in ( requiredTyVars+ , Gen1 (tyVarBndrName lastRequiredTvb) mbLastArgKindName )- return (visibleTvbs', argTys, gk)+ return (requiredTyVars', argTys, gk) -- | Indicates whether Generic(1) is being derived for a plain data type (DataPlain) -- or a data family instance (DataFamily). DataFamily bundles the Name of the data@@ -576,21 +620,6 @@ -- when deriving Generic(1) rankNError :: a rankNError = error "Cannot have polymorphic arguments"---- | Cannot have a Generic(1) instance where the instance head's type is instantiated--- to be a more "saturated" type than the original data declaration. That means--- something like this would be rejected:------ @--- {-# LANGUAGE TypeInType #-}--- data Hm k (a :: k) deriving Generic1--- @------ Since having a Generic1 instance would force k to be instantiated with *,--- resulting in an instance Generic1 (Hm *) instead of instance Generic1 (Hm k).-instantiationError :: Name -> a-instantiationError tyConName = error $- nameBase tyConName ++ " must not be instantiated" -- | Boilerplate for top level splices. --