basicKnownKeyNames
= genericTyConNames
++ monadNames
+ ++ typeableClassNames
++ [ -- Type constructors (synonyms especially)
ioTyConName, ioDataConName,
runIOName,
realFracClassName, -- numeric
realFloatClassName, -- numeric
dataClassName,
- typeableClassName,
-- Numeric stuff
negateName, minusName,
realFloatClassName = clsQual pREL_FLOAT FSLIT("RealFloat") realFloatClassKey
-- Class Ix
-ixClassName = clsQual pREL_ARR FSLIT("Ix") ixClassKey
+ixClassName = clsQual pREL_ARR FSLIT("Ix") ixClassKey
--- Class Typeable and Data
+-- Class Typeable
typeableClassName = clsQual tYPEABLE FSLIT("Typeable") typeableClassKey
-dataClassName = clsQual gENERICS FSLIT("Data") dataClassKey
+typeable1ClassName = clsQual tYPEABLE FSLIT("Typeable") typeable1ClassKey
+typeable2ClassName = clsQual tYPEABLE FSLIT("Typeable") typeable2ClassKey
+typeable3ClassName = clsQual tYPEABLE FSLIT("Typeable") typeable3ClassKey
+typeable4ClassName = clsQual tYPEABLE FSLIT("Typeable") typeable4ClassKey
+typeable5ClassName = clsQual tYPEABLE FSLIT("Typeable") typeable5ClassKey
+typeable6ClassName = clsQual tYPEABLE FSLIT("Typeable") typeable6ClassKey
+typeable7ClassName = clsQual tYPEABLE FSLIT("Typeable") typeable7ClassKey
+
+typeableClassNames = [ typeableClassName, typeable1ClassName, typeable2ClassName
+ , typeable3ClassName, typeable4ClassName, typeable5ClassName
+ , typeable6ClassName, typeable7ClassName ]
+
+-- Class Data
+dataClassName = clsQual gENERICS FSLIT("Data") dataClassKey
-- Error module
assertErrorName = varQual pREL_ERR FSLIT("assertError") assertErrorIdKey
boundedClassKey = mkPreludeClassUnique 1
enumClassKey = mkPreludeClassUnique 2
eqClassKey = mkPreludeClassUnique 3
-typeableClassKey = mkPreludeClassUnique 4
floatingClassKey = mkPreludeClassUnique 5
fractionalClassKey = mkPreludeClassUnique 6
integralClassKey = mkPreludeClassUnique 7
realFloatClassKey = mkPreludeClassUnique 15
realFracClassKey = mkPreludeClassUnique 16
showClassKey = mkPreludeClassUnique 17
-ixClassKey = mkPreludeClassUnique 20
+ixClassKey = mkPreludeClassUnique 18
+
+typeableClassKey = mkPreludeClassUnique 20
+typeable1ClassKey = mkPreludeClassUnique 21
+typeable2ClassKey = mkPreludeClassUnique 22
+typeable3ClassKey = mkPreludeClassUnique 23
+typeable4ClassKey = mkPreludeClassUnique 24
+typeable5ClassKey = mkPreludeClassUnique 25
+typeable6ClassKey = mkPreludeClassUnique 26
+typeable7ClassKey = mkPreludeClassUnique 27
\end{code}
%************************************************************************
import Generics ( mkTyConGenericBinds )
import TcRnMonad
-import TcEnv ( newDFunName,
+import TcEnv ( newDFunName, pprInstInfoDetails,
InstInfo(..), InstBindings(..),
- pprInstInfoDetails, tcLookupTyCon, tcExtendTyVarEnv
+ tcLookupClass, tcLookupTyCon, tcExtendTyVarEnv
)
import TcGenDeriv -- Deriv stuff
import InstEnv ( simpleDFunClassTyCon, extendInstEnv )
import PrelNames
import SrcLoc ( srcLocSpan, Located(..) )
import Util ( zipWithEqual, sortLt, notNull )
-import ListSetOps ( removeDups, assoc )
+import ListSetOps ( removeDups, assocMaybe )
import Outputable
import Bag
\end{code}
------------------------------------------------------------------
derive_these :: [(NewOrData, Name, LHsPred Name)]
-- Find the (nd, TyCon, Pred) pairs that must be `derived'
- -- NB: only source-language decls have deriving, no imported ones do
derive_these = [ (nd, tycon, pred)
| L _ (TyData { tcdND = nd, tcdLName = L _ tycon,
tcdDerivs = Just (L _ preds) }) <- tycl_decls,
------------------------------------------------------------------
mk_eqn_help gla_exts DataType tycon clas tys
| Just err <- checkSideConditions gla_exts clas tycon tys
- = bale_out (derivingThingErr clas tys tycon tyvars err)
+ = bale_out (derivingThingErr clas tys tycon (tyConTyVars tycon) err)
| otherwise
- = new_dfun_name clas tycon `thenM` \ dfun_name ->
- returnM (Just (dfun_name, clas, tycon, tyvars, constraints), Nothing)
- where
- tyvars = tyConTyVars tycon
- constraints = extra_constraints ++ ordinary_constraints
- -- "extra_constraints": see note [Data decl contexts] above
- extra_constraints = tyConTheta tycon
-
- ordinary_constraints
- | clas `hasKey` typeableClassKey -- For the Typeable class, the constraints
- -- don't involve the constructor ags, only
- -- the tycon tyvars
- -- e.g. data T a b = ...
- -- we want
- -- instance (Typeable a, Typable b)
- -- => Typeable (T a b) where
- = [mkClassPred clas [mkTyVarTy tv] | tv <- tyvars]
- | otherwise
- = [ mkClassPred clas [arg_ty]
- | data_con <- tyConDataCons tycon,
- arg_ty <- dataConOrigArgTys data_con,
- -- Use the same type variables
- -- as the type constructor,
- -- hence no need to instantiate
- not (isUnLiftedType arg_ty) -- No constraints for unlifted types?
- ]
+ = do { eqn <- mkDataTypeEqn tycon clas
+ ; returnM (Just eqn, Nothing) }
mk_eqn_help gla_exts NewType tycon clas tys
| can_derive_via_isomorphism && (gla_exts || std_class_via_iso clas)
-- a suitable string; hence the empty type arg list
------------------------------------------------------------------
+mkDataTypeEqn :: TyCon -> Class -> TcM DerivEqn
+mkDataTypeEqn tycon clas
+ | clas `hasKey` typeableClassKey
+ = -- The Typeable class is special in several ways
+ -- data T a b = ... deriving( Typeable )
+ -- gives
+ -- instance Typeable2 T where ...
+ -- 1. There are no constraints in the instance
+ -- 2. There are no type variables either
+ -- 2. The actual class we want to generate isn't necessarily
+ -- Typeable; it depends on the arity of the type
+ do { real_clas <- tcLookupClass (typeableClassNames !! tyConArity tycon)
+ ; dfun_name <- new_dfun_name real_clas tycon
+ ; return (dfun_name, real_clas, tycon, [], []) }
+
+ | otherwise
+ = do { dfun_name <- new_dfun_name clas tycon
+ ; return (dfun_name, clas, tycon, tyvars, constraints) }
+ where
+ tyvars = tyConTyVars tycon
+ constraints = extra_constraints ++ ordinary_constraints
+ extra_constraints = tyConTheta tycon
+ -- "extra_constraints": see note [Data decl contexts] above
+
+ ordinary_constraints
+ = [ mkClassPred clas [arg_ty]
+ | data_con <- tyConDataCons tycon,
+ arg_ty <- dataConOrigArgTys data_con,
+ -- Use the same type variables
+ -- as the type constructor,
+ -- hence no need to instantiate
+ not (isUnLiftedType arg_ty) -- No constraints for unlifted types?
+ ]
+
+
+------------------------------------------------------------------
-- Check side conditions that dis-allow derivability for particular classes
-- This is *apart* from the newtype-deriving mechanism
(tyvars,_,clas,[ty]) = tcSplitDFunTy (idType dfun)
clas_nm = className clas
tycon = tcTyConAppTyCon ty
- (meth_binds, aux_binds) = assoc "gen_bind:bad derived class"
- gen_list (getUnique clas) fix_env tycon
+ (meth_binds, aux_binds) = genDerivBinds clas fix_env tycon
in
-- Bring the right type variables into
-- scope, and rename the method binds
returnM (InstInfo { iDFunId = dfun, iBinds = VanillaInst rn_meth_binds [] },
aux_binds)
-gen_list :: [(Unique, FixityEnv -> TyCon -> (LHsBinds RdrName, LHsBinds RdrName))]
-gen_list = [(eqClassKey, no_aux_binds (ignore_fix_env gen_Eq_binds))
- ,(ordClassKey, no_aux_binds (ignore_fix_env gen_Ord_binds))
- ,(enumClassKey, no_aux_binds (ignore_fix_env gen_Enum_binds))
- ,(boundedClassKey, no_aux_binds (ignore_fix_env gen_Bounded_binds))
- ,(ixClassKey, no_aux_binds (ignore_fix_env gen_Ix_binds))
- ,(typeableClassKey,no_aux_binds (ignore_fix_env gen_Typeable_binds))
- ,(showClassKey, no_aux_binds gen_Show_binds)
- ,(readClassKey, no_aux_binds gen_Read_binds)
- ,(dataClassKey, gen_Data_binds)
- ]
-
- -- no_aux_binds is used for generators that don't
- -- need to produce any auxiliary bindings
-no_aux_binds f fix_env tc = (f fix_env tc, emptyBag)
-ignore_fix_env f fix_env tc = f tc
+genDerivBinds clas fix_env tycon
+ | className clas `elem` typeableClassNames
+ = (gen_Typeable_binds tycon, emptyBag)
+
+ | otherwise
+ = case assocMaybe gen_list (getUnique clas) of
+ Just gen_fn -> gen_fn fix_env tycon
+ Nothing -> pprPanic "genDerivBinds: bad derived class" (ppr clas)
+ where
+ gen_list :: [(Unique, FixityEnv -> TyCon -> (LHsBinds RdrName, LHsBinds RdrName))]
+ gen_list = [(eqClassKey, no_aux_binds (ignore_fix_env gen_Eq_binds))
+ ,(ordClassKey, no_aux_binds (ignore_fix_env gen_Ord_binds))
+ ,(enumClassKey, no_aux_binds (ignore_fix_env gen_Enum_binds))
+ ,(boundedClassKey, no_aux_binds (ignore_fix_env gen_Bounded_binds))
+ ,(ixClassKey, no_aux_binds (ignore_fix_env gen_Ix_binds))
+ ,(typeableClassKey,no_aux_binds (ignore_fix_env gen_Typeable_binds))
+ ,(showClassKey, no_aux_binds gen_Show_binds)
+ ,(readClassKey, no_aux_binds gen_Read_binds)
+ ,(dataClassKey, gen_Data_binds)
+ ]
+
+ -- no_aux_binds is used for generators that don't
+ -- need to produce any auxiliary bindings
+ no_aux_binds f fix_env tc = (f fix_env tc, emptyBag)
+ ignore_fix_env f fix_env tc = f tc
\end{code}
import MkId ( eRROR_ID )
import PrimOp ( PrimOp(..) )
import SrcLoc ( Located(..), noLoc, srcLocSpan )
-import TyCon ( TyCon, isNewTyCon, tyConDataCons, isEnumerationTyCon,
+import TyCon ( TyCon, isNewTyCon, tyConDataCons, isEnumerationTyCon, tyConArity,
maybeTyConSingleCon, tyConFamilySize, tyConTyVars, tyConName
)
import TcType ( isUnLiftedType, tcEqType, Type )
we generate
- instance (Typeable a, Typeable b) => Typeable (T a b) where
- typeOf _ = mkTypeRep (mkTyConRep "T")
- [typeOf (undefined::a),
- typeOf (undefined::b)]
+ instance Typeable2 T where
+ typeOf2 _ = mkAppTy (mkTyConRep "T") []
-Notice the use of lexically scoped type variables.
+We are passed the Typeable2 class as well as T
\begin{code}
gen_Typeable_binds :: TyCon -> LHsBinds RdrName
gen_Typeable_binds tycon
= unitBag $
- mk_easy_FunBind tycon_loc typeOf_RDR [wildPat] emptyBag
- (nlHsApps mkTypeRep_RDR [tycon_rep, arg_reps])
+ mk_easy_FunBind tycon_loc
+ (mk_typeOf_RDR tycon) -- Name of appropriate type0f function
+ [wildPat] emptyBag
+ (nlHsApps mkTypeRep_RDR [tycon_rep, nlList []])
where
tycon_loc = getSrcSpan tycon
- tyvars = tyConTyVars tycon
tycon_rep = nlHsVar mkTyConRep_RDR `nlHsApp` nlHsLit (mkHsString (showSDoc (ppr tycon)))
- arg_reps = nlList (map mk tyvars)
- mk tyvar = nlHsApp (nlHsVar typeOf_RDR)
- (noLoc (ExprWithTySig (nlHsVar undefined_RDR)
- (nlHsTyVar (getRdrName tyvar))))
+
+mk_typeOf_RDR :: TyCon -> RdrName
+-- Use the arity of the TyCon to make the right typeOfn function
+mk_typeOf_RDR tycon = varQual_RDR tYPEABLE_Name (mkFastString ("typeOf" ++ suffix))
+ where
+ arity = tyConArity tycon
+ suffix | arity == 0 = ""
+ | otherwise = show arity
\end{code}