{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
module Generics.Deriving.TH (
deriveMeta
, deriveData
, deriveConstructors
, deriveSelectors
, deriveAll
, deriveAll0
, deriveAll1
, deriveAll0And1
, deriveRepresentable0
, deriveRepresentable1
, deriveRep0
, deriveRep1
, makeRep0Inline
, makeRep0
, makeRep0FromType
, makeFrom
, makeFrom0
, makeTo
, makeTo0
, makeRep1Inline
, makeRep1
, makeRep1FromType
, makeFrom1
, makeTo1
, Options(..)
, defaultOptions
, RepOptions(..)
, defaultRepOptions
, KindSigOptions
, defaultKindSigOptions
, EmptyCaseOptions
, defaultEmptyCaseOptions
, deriveAll0Options
, deriveAll1Options
, deriveAll0And1Options
, deriveRepresentable0Options
, deriveRepresentable1Options
, deriveRep0Options
, deriveRep1Options
, makeFrom0Options
, makeTo0Options
, makeFrom1Options
, makeTo1Options
) where
import Control.Monad ((>=>), unless, when)
import qualified Data.Map as Map (empty, fromList)
import Generics.Deriving.TH.Internal
#if MIN_VERSION_base(4,9,0)
import Generics.Deriving.TH.Post4_9
#else
import Generics.Deriving.TH.Pre4_9
#endif
import Language.Haskell.TH.Datatype
import Language.Haskell.TH.Lib
import Language.Haskell.TH
data Options = Options
{ repOptions :: RepOptions
, kindSigOptions :: KindSigOptions
, emptyCaseOptions :: EmptyCaseOptions
} deriving (Eq, Ord, Read, Show)
defaultOptions :: Options
defaultOptions = Options
{ repOptions = defaultRepOptions
, kindSigOptions = defaultKindSigOptions
, emptyCaseOptions = defaultEmptyCaseOptions
}
data RepOptions = InlineRep
| TypeSynonymRep
deriving (Eq, Ord, Read, Show)
defaultRepOptions :: RepOptions
defaultRepOptions = InlineRep
type KindSigOptions = Bool
defaultKindSigOptions :: KindSigOptions
defaultKindSigOptions = True
type EmptyCaseOptions = Bool
defaultEmptyCaseOptions :: EmptyCaseOptions
defaultEmptyCaseOptions = False
deriveAll :: Name -> Q [Dec]
deriveAll = deriveAll0
deriveAll0 :: Name -> Q [Dec]
deriveAll0 = deriveAll0Options defaultOptions
deriveAll0Options :: Options -> Name -> Q [Dec]
deriveAll0Options = deriveAllCommon True False
deriveAll1 :: Name -> Q [Dec]
deriveAll1 = deriveAll1Options defaultOptions
deriveAll1Options :: Options -> Name -> Q [Dec]
deriveAll1Options = deriveAllCommon False True
deriveAll0And1 :: Name -> Q [Dec]
deriveAll0And1 = deriveAll0And1Options defaultOptions
deriveAll0And1Options :: Options -> Name -> Q [Dec]
deriveAll0And1Options = deriveAllCommon True True
deriveAllCommon :: Bool -> Bool -> Options -> Name -> Q [Dec]
deriveAllCommon generic generic1 opts n = do
a <- deriveMeta n
b <- if generic
then deriveRepresentableCommon Generic opts n
else return []
c <- if generic1
then deriveRepresentableCommon Generic1 opts n
else return []
return (a ++ b ++ c)
deriveRepresentable0 :: Name -> Q [Dec]
deriveRepresentable0 = deriveRepresentable0Options defaultOptions
deriveRepresentable0Options :: Options -> Name -> Q [Dec]
deriveRepresentable0Options = deriveRepresentableCommon Generic
deriveRepresentable1 :: Name -> Q [Dec]
deriveRepresentable1 = deriveRepresentable1Options defaultOptions
deriveRepresentable1Options :: Options -> Name -> Q [Dec]
deriveRepresentable1Options = deriveRepresentableCommon Generic1
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)
deriveRep0 :: Name -> Q [Dec]
deriveRep0 = deriveRep0Options defaultKindSigOptions
deriveRep0Options :: KindSigOptions -> Name -> Q [Dec]
deriveRep0Options = deriveRepCommon Generic
deriveRep1 :: Name -> Q [Dec]
deriveRep1 = deriveRep1Options defaultKindSigOptions
deriveRep1Options :: KindSigOptions -> Name -> Q [Dec]
deriveRep1Options = deriveRepCommon Generic1
deriveRepCommon :: GenericClass -> KindSigOptions -> Name -> Q [Dec]
deriveRepCommon gClass useKindSigs n = do
i <- reifyDataInfo n
let (name, instTys, cons, dv) = either error id i
!_ <- buildTypeInstance gClass useKindSigs name instTys
let (tySynVars, gk) = genericKind gClass instTys
tySynVars' = if useKindSigs
then tySynVars
else map unKindedTV tySynVars
fmap (:[]) $ tySynD (genRepName gClass dv name)
tySynVars'
(repType gk dv name Map.empty cons)
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
-> Options
-> Name
-> Q [Dec]
deriveInstCommon genericName repName gClass fromName toName opts n = do
i <- reifyDataInfo n
let (name, instTys, cons, dv) = either error id i
useKindSigs = kindSigOptions opts
!(origTy, origKind) <- buildTypeInstance gClass useKindSigs name instTys
tyInsRHS <- if repOptions opts == InlineRep
then makeRepInline gClass dv name instTys cons origTy
else makeRepTySynApp gClass dv name origTy
let origSigTy = if useKindSigs
then SigT origTy origKind
else origTy
tyIns <- tySynInstDCompat repName Nothing [return origSigTy] (return tyInsRHS)
let ecOptions = emptyCaseOptions opts
mkBody maker = [clause [] (normalB $
mkCaseExp gClass ecOptions name instTys cons maker) []]
fcs = mkBody mkFrom
tcs = mkBody mkTo
fmap (:[]) $
instanceD (cxt []) (conT genericName `appT` return origSigTy)
[return tyIns, funD fromName fcs, funD toName tcs]
makeRep0Inline :: Name -> Q Type -> Q Type
makeRep0Inline n = makeRepCommon Generic InlineRep n . Just
makeRep1Inline :: Name -> Q Type -> Q Type
makeRep1Inline n = makeRepCommon Generic1 InlineRep n . Just
makeRep0 :: Name -> Q Type
makeRep0 n = makeRepCommon Generic TypeSynonymRep n Nothing
makeRep1 :: Name -> Q Type
makeRep1 n = makeRepCommon Generic1 TypeSynonymRep n Nothing
makeRep0FromType :: Name -> Q Type -> Q Type
makeRep0FromType n = makeRepCommon Generic TypeSynonymRep n . Just
makeRep1FromType :: Name -> Q Type -> Q Type
makeRep1FromType n = makeRepCommon Generic1 TypeSynonymRep n . Just
makeRepCommon :: GenericClass
-> RepOptions
-> Name
-> Maybe (Q Type)
-> Q Type
makeRepCommon gClass repOpts n mbQTy = do
i <- reifyDataInfo n
let (name, instTys, cons, dv) = either error id i
!_ <- buildTypeInstance gClass False name instTys
case (mbQTy, repOpts) of
(Just qTy, TypeSynonymRep) -> qTy >>= makeRepTySynApp gClass dv name
(Just qTy, InlineRep) -> qTy >>= makeRepInline gClass dv name instTys cons
(Nothing, TypeSynonymRep) -> conT $ genRepName gClass dv name
(Nothing, InlineRep) -> fail "makeRepCommon"
makeRepInline :: GenericClass
-> DatatypeVariant_
-> Name
-> [Type]
-> [ConstructorInfo]
-> Type
-> Q Type
makeRepInline gClass dv name instTys cons ty = do
let instVars = freeVariablesWellScoped [ty]
(tySynVars, gk) = genericKind gClass instTys
typeSubst :: TypeSubst
typeSubst = Map.fromList $
zip (map tvName tySynVars)
(map (VarT . tvName) instVars)
repType gk dv name typeSubst cons
makeRepTySynApp :: GenericClass -> DatatypeVariant_ -> Name
-> Type -> Q Type
makeRepTySynApp gClass dv name ty =
let instTvbs = map unKindedTV $ freeVariablesWellScoped [ty]
in return $ applyTyToTvbs (genRepName gClass dv name) instTvbs
makeFrom :: Name -> Q Exp
makeFrom = makeFrom0
makeFrom0 :: Name -> Q Exp
makeFrom0 = makeFrom0Options defaultEmptyCaseOptions
makeFrom0Options :: EmptyCaseOptions -> Name -> Q Exp
makeFrom0Options = makeFunCommon mkFrom Generic
makeTo :: Name -> Q Exp
makeTo = makeTo0
makeTo0 :: Name -> Q Exp
makeTo0 = makeTo0Options defaultEmptyCaseOptions
makeTo0Options :: EmptyCaseOptions -> Name -> Q Exp
makeTo0Options = makeFunCommon mkTo Generic
makeFrom1 :: Name -> Q Exp
makeFrom1 = makeFrom1Options defaultEmptyCaseOptions
makeFrom1Options :: EmptyCaseOptions -> Name -> Q Exp
makeFrom1Options = makeFunCommon mkFrom Generic1
makeTo1 :: Name -> Q Exp
makeTo1 = makeTo1Options defaultEmptyCaseOptions
makeTo1Options :: EmptyCaseOptions -> Name -> Q Exp
makeTo1Options = makeFunCommon mkTo Generic1
makeFunCommon
:: (GenericClass -> EmptyCaseOptions -> Int -> Int -> Name -> [Type]
-> [ConstructorInfo] -> Q Match)
-> GenericClass -> EmptyCaseOptions -> Name -> Q Exp
makeFunCommon maker gClass ecOptions n = do
i <- reifyDataInfo n
let (name, instTys, cons, _) = either error id i
buildTypeInstance gClass False name instTys
`seq` mkCaseExp gClass ecOptions name instTys cons maker
genRepName :: GenericClass -> DatatypeVariant_
-> Name -> Name
genRepName gClass dv n
= mkName
. showsDatatypeVariant dv
. (("Rep" ++ show (fromEnum gClass)) ++)
. ((showNameQual n ++ "_") ++)
. sanitizeName
$ nameBase n
repType :: GenericKind
-> DatatypeVariant_
-> Name
-> TypeSubst
-> [ConstructorInfo]
-> Q Type
repType gk dv dt typeSubst cs =
conT d1TypeName `appT` mkMetaDataType dv dt `appT`
foldBal sum' (conT v1TypeName) (map (repCon gk dv dt typeSubst) cs)
where
sum' :: Q Type -> Q Type -> Q Type
sum' a b = conT sumTypeName `appT` a `appT` b
repCon :: GenericKind
-> DatatypeVariant_
-> Name
-> TypeSubst
-> ConstructorInfo
-> Q Type
repCon gk dv dt typeSubst
(ConstructorInfo { constructorName = n
, constructorVars = vars
, constructorContext = ctxt
, constructorStrictness = bangs
, constructorFields = ts
, constructorVariant = cv
}) = do
checkExistentialContext n vars ctxt
let mbSelNames = case cv of
NormalConstructor -> Nothing
InfixConstructor -> Nothing
RecordConstructor selNames -> Just selNames
isRecord = case cv of
NormalConstructor -> False
InfixConstructor -> False
RecordConstructor _ -> True
isInfix = case cv of
NormalConstructor -> False
InfixConstructor -> True
RecordConstructor _ -> False
ssis <- reifySelStrictInfo n bangs
repConWith gk dv dt n typeSubst mbSelNames ssis ts isRecord isInfix
repConWith :: GenericKind
-> DatatypeVariant_
-> Name
-> Name
-> TypeSubst
-> Maybe [Name]
-> [SelStrictInfo]
-> [Type]
-> Bool
-> Bool
-> Q Type
repConWith gk dv dt n typeSubst mbSelNames ssis ts isRecord isInfix = do
let structureType :: Q Type
structureType = foldBal prodT (conT u1TypeName) f
f :: [Q Type]
f = case mbSelNames of
Just selNames -> zipWith3 (repField gk dv dt n typeSubst . Just)
selNames ssis ts
Nothing -> zipWith (repField gk dv dt n typeSubst Nothing)
ssis ts
conT c1TypeName
`appT` mkMetaConsType dv dt n isRecord isInfix
`appT` structureType
prodT :: Q Type -> Q Type -> Q Type
prodT a b = conT productTypeName `appT` a `appT` b
repField :: GenericKind
-> DatatypeVariant_
-> Name
-> Name
-> TypeSubst
-> Maybe Name
-> SelStrictInfo
-> Type
-> Q Type
repField gk dv dt ns typeSubst mbF ssi t =
conT s1TypeName
`appT` mkMetaSelType dv dt ns mbF ssi
`appT` (repFieldArg gk =<< resolveTypeSynonyms t'')
where
t', t'' :: Type
t' = case gk of
Gen1 _ (Just _kvName) ->
#if MIN_VERSION_base(4,10,0)
t
#else
substNameWithKind _kvName starK t
#endif
_ -> t
t'' = applySubstitution typeSubst t'
repFieldArg :: GenericKind -> Type -> Q Type
repFieldArg _ ForallT{} = rankNError
repFieldArg gk (SigT t _) = repFieldArg gk t
repFieldArg Gen0 t = boxT t
repFieldArg (Gen1 name _) (VarT t) | t == name = conT par1TypeName
repFieldArg gk@(Gen1 name _) t = do
let (tyHead, tyArgs) = unapplyTy t
numLastArgs = min 1 $ length tyArgs
(lhsArgs, rhsArgs) = splitAt (length tyArgs - numLastArgs) tyArgs
rec0Type = boxT t
phiType = return $ applyTyToTys tyHead lhsArgs
inspectTy :: Type -> Q Type
inspectTy (VarT a)
| a == name
= conT rec1TypeName `appT` phiType
inspectTy (SigT ty _) = inspectTy ty
inspectTy beta
| not (ground beta name)
= conT composeTypeName `appT` phiType
`appT` repFieldArg gk beta
inspectTy _ = rec0Type
itf <- isInTypeFamilyApp name tyHead tyArgs
if any (not . (`ground` name)) lhsArgs || itf
then outOfPlaceTyVarError
else case rhsArgs of
[] -> rec0Type
ty:_ -> inspectTy ty
boxT :: Type -> Q Type
boxT ty = case unboxedRepNames ty of
Just (boxTyName, _, _) -> conT boxTyName
Nothing -> conT rec0TypeName `appT` return ty
mkCaseExp
:: GenericClass -> EmptyCaseOptions -> Name -> [Type] -> [ConstructorInfo]
-> (GenericClass -> EmptyCaseOptions -> Int -> Int -> Name -> [Type]
-> [ConstructorInfo] -> Q Match)
-> Q Exp
mkCaseExp gClass ecOptions dt instTys cs matchmaker = do
val <- newName "val"
lam1E (varP val) $ caseE (varE val) [matchmaker gClass ecOptions 1 1 dt instTys cs]
mkFrom :: GenericClass -> EmptyCaseOptions -> Int -> Int -> Name -> [Type]
-> [ConstructorInfo] -> Q Match
mkFrom gClass ecOptions m i dt instTys cs = do
y <- newName "y"
match (varP y)
(normalB $ conE m1DataName `appE` caseE (varE y) cases)
[]
where
cases = case cs of
[] -> errorFrom ecOptions dt
_ -> zipWith (fromCon gk wrapE (length cs)) [1..] cs
wrapE e = lrE i m e
(_, gk) = genericKind gClass instTys
errorFrom :: EmptyCaseOptions -> Name -> [Q Match]
errorFrom useEmptyCase dt
| useEmptyCase && ghc7'8OrLater
= []
| otherwise
= [do z <- newName "z"
match
(varP z)
(normalB $
appE (varE seqValName) (varE z) `appE`
appE (varE errorValName)
(stringE $ "No generic representation for empty datatype "
++ nameBase dt))
[]]
mkTo :: GenericClass -> EmptyCaseOptions -> Int -> Int -> Name -> [Type]
-> [ConstructorInfo] -> Q Match
mkTo gClass ecOptions m i dt instTys cs = do
y <- newName "y"
match (conP m1DataName [varP y])
(normalB $ caseE (varE y) cases)
[]
where
cases = case cs of
[] -> errorTo ecOptions dt
_ -> zipWith (toCon gk wrapP (length cs)) [1..] cs
wrapP p = lrP i m p
(_, gk) = genericKind gClass instTys
errorTo :: EmptyCaseOptions -> Name -> [Q Match]
errorTo useEmptyCase dt
| useEmptyCase && ghc7'8OrLater
= []
| otherwise
= [do z <- newName "z"
match
(varP z)
(normalB $
appE (varE seqValName) (varE z) `appE`
appE (varE errorValName)
(stringE $ "No values for empty datatype " ++ nameBase dt))
[]]
ghc7'8OrLater :: Bool
#if __GLASGOW_HASKELL__ >= 708
ghc7'8OrLater = True
#else
ghc7'8OrLater = False
#endif
fromCon :: GenericKind -> (Q Exp -> Q Exp) -> Int -> Int
-> ConstructorInfo -> Q Match
fromCon gk wrap m i
(ConstructorInfo { constructorName = cn
, constructorVars = vars
, constructorContext = ctxt
, constructorFields = ts
}) = do
checkExistentialContext cn vars ctxt
fNames <- newNameList "f" $ length ts
match (conP cn (map varP fNames))
(normalB $ wrap $ lrE i m $ conE m1DataName `appE`
foldBal prodE (conE u1DataName) (zipWith (fromField gk) fNames ts)) []
prodE :: Q Exp -> Q Exp -> Q Exp
prodE x y = conE productDataName `appE` x `appE` y
fromField :: GenericKind -> Name -> Type -> Q Exp
fromField gk nr t = conE m1DataName `appE` (fromFieldWrap gk nr =<< resolveTypeSynonyms t)
fromFieldWrap :: GenericKind -> Name -> Type -> Q Exp
fromFieldWrap _ _ ForallT{} = rankNError
fromFieldWrap gk nr (SigT t _) = fromFieldWrap gk nr t
fromFieldWrap Gen0 nr t = conE (boxRepName t) `appE` varE nr
fromFieldWrap (Gen1 name _) nr t = wC t name `appE` varE nr
wC :: Type -> Name -> Q Exp
wC (VarT t) name | t == name = conE par1DataName
wC t name
| ground t name = conE $ boxRepName t
| otherwise = do
let (tyHead, tyArgs) = unapplyTy t
numLastArgs = min 1 $ length tyArgs
(lhsArgs, rhsArgs) = splitAt (length tyArgs - numLastArgs) tyArgs
inspectTy :: Type -> Q Exp
inspectTy ForallT{} = rankNError
inspectTy (SigT ty _) = inspectTy ty
inspectTy (VarT a)
| a == name
= conE rec1DataName
inspectTy beta = infixApp (conE comp1DataName)
(varE composeValName)
(varE fmapValName `appE` wC beta name)
itf <- isInTypeFamilyApp name tyHead tyArgs
if any (not . (`ground` name)) lhsArgs || itf
then outOfPlaceTyVarError
else case rhsArgs of
[] -> conE $ boxRepName t
ty:_ -> inspectTy ty
boxRepName :: Type -> Name
boxRepName = maybe k1DataName snd3 . unboxedRepNames
toCon :: GenericKind -> (Q Pat -> Q Pat) -> Int -> Int
-> ConstructorInfo -> Q Match
toCon gk wrap m i
(ConstructorInfo { constructorName = cn
, constructorVars = vars
, constructorContext = ctxt
, constructorFields = ts
}) = do
checkExistentialContext cn vars ctxt
fNames <- newNameList "f" $ length ts
match (wrap $ lrP i m $ conP m1DataName
[foldBal prod (conP u1DataName []) (zipWith (toField gk) fNames ts)])
(normalB $ foldl appE (conE cn)
(zipWith (\nr -> resolveTypeSynonyms >=> toConUnwC gk nr)
fNames ts)) []
where prod x y = conP productDataName [x,y]
toConUnwC :: GenericKind -> Name -> Type -> Q Exp
toConUnwC Gen0 nr _ = varE nr
toConUnwC (Gen1 name _) nr t = unwC t name `appE` varE nr
toField :: GenericKind -> Name -> Type -> Q Pat
toField gk nr t = conP m1DataName [toFieldWrap gk nr t]
toFieldWrap :: GenericKind -> Name -> Type -> Q Pat
toFieldWrap Gen0 nr t = conP (boxRepName t) [varP nr]
toFieldWrap Gen1{} nr _ = varP nr
unwC :: Type -> Name -> Q Exp
unwC (SigT t _) name = unwC t name
unwC (VarT t) name | t == name = varE unPar1ValName
unwC t name
| ground t name = varE $ unboxRepName t
| otherwise = do
let (tyHead, tyArgs) = unapplyTy t
numLastArgs = min 1 $ length tyArgs
(lhsArgs, rhsArgs) = splitAt (length tyArgs - numLastArgs) tyArgs
inspectTy :: Type -> Q Exp
inspectTy ForallT{} = rankNError
inspectTy (SigT ty _) = inspectTy ty
inspectTy (VarT a)
| a == name
= varE unRec1ValName
inspectTy beta = infixApp (varE fmapValName `appE` unwC beta name)
(varE composeValName)
(varE unComp1ValName)
itf <- isInTypeFamilyApp name tyHead tyArgs
if any (not . (`ground` name)) lhsArgs || itf
then outOfPlaceTyVarError
else case rhsArgs of
[] -> varE $ unboxRepName t
ty:_ -> inspectTy ty
unboxRepName :: Type -> Name
unboxRepName = maybe unK1ValName trd3 . unboxedRepNames
lrP :: Int -> Int -> (Q Pat -> Q Pat)
lrP i n p
| n == 0 = fail "lrP: impossible"
| n == 1 = p
| i <= div n 2 = conP l1DataName [lrP i (div n 2) p]
| otherwise = conP r1DataName [lrP (i-m) (n-m) p]
where m = div n 2
lrE :: Int -> Int -> (Q Exp -> Q Exp)
lrE i n e
| n == 0 = fail "lrE: impossible"
| n == 1 = e
| i <= div n 2 = conE l1DataName `appE` lrE i (div n 2) e
| otherwise = conE r1DataName `appE` lrE (i-m) (n-m) e
where m = div n 2
unboxedRepNames :: Type -> Maybe (Name, Name, Name)
unboxedRepNames ty
| ty == ConT addrHashTypeName = Just (uAddrTypeName, uAddrDataName, uAddrHashValName)
| ty == ConT charHashTypeName = Just (uCharTypeName, uCharDataName, uCharHashValName)
| ty == ConT doubleHashTypeName = Just (uDoubleTypeName, uDoubleDataName, uDoubleHashValName)
| ty == ConT floatHashTypeName = Just (uFloatTypeName, uFloatDataName, uFloatHashValName)
| ty == ConT intHashTypeName = Just (uIntTypeName, uIntDataName, uIntHashValName)
| ty == ConT wordHashTypeName = Just (uWordTypeName, uWordDataName, uWordHashValName)
| otherwise = Nothing
buildTypeInstance :: GenericClass
-> KindSigOptions
-> Name
-> [Type]
-> Q (Type, Kind)
buildTypeInstance gClass useKindSigs tyConName varTysOrig = do
varTysExp <- mapM resolveTypeSynonyms varTysOrig
let remainingLength :: Int
remainingLength = length varTysOrig - fromEnum gClass
droppedTysExp :: [Type]
droppedTysExp = drop remainingLength varTysExp
droppedStarKindStati :: [StarKindStatus]
droppedStarKindStati = map canRealizeKindStar droppedTysExp
when (remainingLength < 0 || any (== NotKindStar) droppedStarKindStati) $
derivingKindError tyConName
let varTysExpSubst :: [Type]
#if MIN_VERSION_base(4,10,0)
varTysExpSubst = varTysExp
#else
varTysExpSubst = map (substNamesWithKindStar droppedKindVarNames) varTysExp
droppedKindVarNames :: [Name]
droppedKindVarNames = catKindVarNames droppedStarKindStati
#endif
let remainingTysExpSubst, droppedTysExpSubst :: [Type]
(remainingTysExpSubst, droppedTysExpSubst) =
splitAt remainingLength varTysExpSubst
#if !(MIN_VERSION_base(4,10,0))
unless (all hasKindStar droppedTysExpSubst) $
derivingKindError tyConName
#endif
let varTysOrigSubst :: [Type]
varTysOrigSubst =
#if MIN_VERSION_base(4,10,0)
id
#else
map (substNamesWithKindStar droppedKindVarNames)
#endif
$ varTysOrig
remainingTysOrigSubst, droppedTysOrigSubst :: [Type]
(remainingTysOrigSubst, droppedTysOrigSubst) =
splitAt remainingLength varTysOrigSubst
remainingTysOrigSubst' :: [Type]
remainingTysOrigSubst' =
if useKindSigs
then remainingTysOrigSubst
else map unSigT remainingTysOrigSubst
instanceType :: Type
instanceType = applyTyToTys (ConT tyConName) remainingTysOrigSubst'
instanceKind :: Kind
instanceKind = makeFunKind (map typeKind droppedTysOrigSubst) starK
unless (canEtaReduce remainingTysExpSubst droppedTysExpSubst) $
etaReductionError instanceType
return (instanceType, instanceKind)