-makeDerivEqns overlap_flag tycl_decls
- = mapAndUnzipM mk_eqn derive_these `thenM` \ (maybe_ordinaries, maybe_newtypes) ->
- returnM (catMaybes maybe_ordinaries, catMaybes maybe_newtypes)
- where
- ------------------------------------------------------------------
- derive_these :: [(NewOrData, Name, LHsType Name)]
- -- Find the (nd, TyCon, Pred) pairs that must be `derived'
- derive_these = [ (nd, tycon, pred)
- | L _ (TyData { tcdND = nd, tcdLName = L _ tycon,
- tcdDerivs = Just preds }) <- tycl_decls,
- pred <- preds ]
-
- ------------------------------------------------------------------
- mk_eqn :: (NewOrData, Name, LHsType Name) -> TcM (Maybe DerivEqn, Maybe InstInfo)
- -- We swizzle the tyvars and datacons out of the tycon
- -- to make the rest of the equation
- --
- -- The "deriv_ty" is a LHsType to take account of the fact that for newtype derivign
- -- we allow deriving (forall a. C [a]).
-
- mk_eqn (new_or_data, tycon_name, hs_deriv_ty)
- = tcLookupTyCon tycon_name `thenM` \ tycon ->
- setSrcSpan (srcLocSpan (getSrcLoc tycon)) $
- addErrCtxt (derivCtxt Nothing tycon) $
- tcExtendTyVarEnv (tyConTyVars tycon) $ -- Deriving preds may (now) mention
- -- the type variables for the type constructor
- tcHsDeriv hs_deriv_ty `thenM` \ (deriv_tvs, clas, tys) ->
- doptM Opt_GlasgowExts `thenM` \ gla_exts ->
- mk_eqn_help gla_exts new_or_data tycon deriv_tvs clas tys
-
- ------------------------------------------------------------------
- mk_eqn_help gla_exts DataType tycon deriv_tvs clas tys
- | Just err <- checkSideConditions gla_exts tycon deriv_tvs clas tys
- = bale_out (derivingThingErr clas tys tycon (tyConTyVars tycon) err)
- | otherwise
- = do { eqn <- mkDataTypeEqn tycon clas
- ; returnM (Just eqn, Nothing) }
-
- mk_eqn_help gla_exts NewType tycon deriv_tvs clas tys
- | can_derive_via_isomorphism && (gla_exts || std_class_via_iso clas)
- = -- Go ahead and use the isomorphism
- traceTc (text "newtype deriving:" <+> ppr tycon <+> ppr rep_tys) `thenM_`
- new_dfun_name clas tycon `thenM` \ dfun_name ->
- returnM (Nothing, Just (InstInfo { iSpec = mk_inst_spec dfun_name,
- iBinds = NewTypeDerived rep_tys }))
- | std_class gla_exts clas
- = mk_eqn_help gla_exts DataType tycon deriv_tvs clas tys -- Go via bale-out route
-
- | otherwise -- Non-standard instance
- = bale_out (if gla_exts then
- cant_derive_err -- Too hard
- else
- non_std_err) -- Just complain about being a non-std instance
- where
- -- Here is the plan for newtype derivings. We see
- -- newtype T a1...an = T (t ak...an) deriving (.., C s1 .. sm, ...)
- -- where t is a type,
- -- ak...an is a suffix of a1..an
- -- ak...an do not occur free in t,
- -- (C s1 ... sm) is a *partial applications* of class C
- -- with the last parameter missing
- --
- -- We generate the instances
- -- instance C s1 .. sm (t ak...ap) => C s1 .. sm (T a1...ap)
- -- where T a1...ap is the partial application of the LHS of the correct kind
- -- and p >= k
- --
- -- Running example: newtype T s a = MkT (ST s a) deriving( Monad )
- -- instance Monad (ST s) => Monad (T s) where
- -- fail = coerce ... (fail @ ST s)
- -- (Actually we don't need the coerce, because non-rec newtypes are transparent
-
- clas_tyvars = classTyVars clas
- kind = tyVarKind (last clas_tyvars)
- -- Kind of the thing we want to instance
- -- e.g. argument kind of Monad, *->*
-
- (arg_kinds, _) = splitKindFunTys kind
- n_args_to_drop = length arg_kinds
- -- Want to drop 1 arg from (T s a) and (ST s a)
- -- to get instance Monad (ST s) => Monad (T s)
-
- -- Note [newtype representation]
- -- Need newTyConRhs *not* newTyConRep to get the representation
- -- type, because the latter looks through all intermediate newtypes
- -- For example
- -- newtype B = MkB Int
- -- newtype A = MkA B deriving( Num )
- -- We want the Num instance of B, *not* the Num instance of Int,
- -- when making the Num instance of A!
- (tc_tvs, rep_ty) = newTyConRhs tycon
- (rep_fn, rep_ty_args) = tcSplitAppTys rep_ty
-
- n_tyvars_to_keep = tyConArity tycon - n_args_to_drop
- tyvars_to_drop = drop n_tyvars_to_keep tc_tvs
- tyvars_to_keep = take n_tyvars_to_keep tc_tvs
-
- n_args_to_keep = length rep_ty_args - n_args_to_drop
- args_to_drop = drop n_args_to_keep rep_ty_args
- args_to_keep = take n_args_to_keep rep_ty_args
-
- rep_fn' = mkAppTys rep_fn args_to_keep
- rep_tys = tys ++ [rep_fn']
- rep_pred = mkClassPred clas rep_tys
- -- rep_pred is the representation dictionary, from where
- -- we are gong to get all the methods for the newtype dictionary
-
- inst_tys = (tys ++ [mkTyConApp tycon (mkTyVarTys tyvars_to_keep)])
- -- The 'tys' here come from the partial application
- -- in the deriving clause. The last arg is the new
- -- instance type.
-
- -- We must pass the superclasses; the newtype might be an instance
- -- of them in a different way than the representation type
- -- E.g. newtype Foo a = Foo a deriving( Show, Num, Eq )
- -- Then the Show instance is not done via isomprphism; it shows
- -- Foo 3 as "Foo 3"
- -- The Num instance is derived via isomorphism, but the Show superclass
- -- dictionary must the Show instance for Foo, *not* the Show dictionary
- -- gotten from the Num dictionary. So we must build a whole new dictionary
- -- not just use the Num one. The instance we want is something like:
- -- instance (Num a, Show (Foo a), Eq (Foo a)) => Num (Foo a) where
- -- (+) = ((+)@a)
- -- ...etc...
- -- There's no 'corece' needed because after the type checker newtypes
- -- are transparent.
-
- sc_theta = substTheta (zipOpenTvSubst clas_tyvars inst_tys)
- (classSCTheta clas)
-
- -- If there are no tyvars, there's no need
- -- to abstract over the dictionaries we need
- dict_tvs = deriv_tvs ++ tc_tvs
- dict_args | null dict_tvs = []
- | otherwise = rep_pred : sc_theta
-
- -- Finally! Here's where we build the dictionary Id
- mk_inst_spec dfun_name
- = mkLocalInstance dfun overlap_flag
- where
- dfun = mkDictFunId dfun_name dict_tvs dict_args clas inst_tys
-
- -------------------------------------------------------------------
- -- Figuring out whether we can only do this newtype-deriving thing
-
- right_arity = length tys + 1 == classArity clas
-
- -- Never derive Read,Show,Typeable,Data this way
- non_iso_classes = [readClassKey, showClassKey, typeableClassKey, dataClassKey]
- can_derive_via_isomorphism
- = not (getUnique clas `elem` non_iso_classes)
- && right_arity -- Well kinded;
- -- eg not: newtype T ... deriving( ST )
- -- because ST needs *2* type params
- && n_tyvars_to_keep >= 0 -- Type constructor has right kind:
- -- eg not: newtype T = T Int deriving( Monad )
- && n_args_to_keep >= 0 -- Rep type has right kind:
- -- eg not: newtype T a = T Int deriving( Monad )
- && eta_ok -- Eta reduction works
- && not (isRecursiveTyCon tycon) -- Does not work for recursive tycons:
- -- newtype A = MkA [A]
- -- Don't want
- -- instance Eq [A] => Eq A !!
- -- Here's a recursive newtype that's actually OK
- -- newtype S1 = S1 [T1 ()]
- -- newtype T1 a = T1 (StateT S1 IO a ) deriving( Monad )
- -- It's currently rejected. Oh well.
- -- In fact we generate an instance decl that has method of form
- -- meth @ instTy = meth @ repTy
- -- (no coerce's). We'd need a coerce if we wanted to handle
- -- recursive newtypes too
-
- -- Check that eta reduction is OK
- -- (a) the dropped-off args are identical
- -- (b) the remaining type args mention
- -- only the remaining type variables
- eta_ok = (args_to_drop `tcEqTypes` mkTyVarTys tyvars_to_drop)
- && (tyVarsOfType rep_fn' `subVarSet` mkVarSet tyvars_to_keep)