import Subst ( mkTyVarSubst, substTheta )
import ErrUtils ( dumpIfSet_dyn )
import MkId ( mkDictFunId )
-import DataCon ( dataConRepArgTys, isNullaryDataCon, isExistentialDataCon )
+import DataCon ( dataConRepArgTys, dataConOrigArgTys, isNullaryDataCon, isExistentialDataCon )
import Maybes ( maybeToBool, catMaybes )
import Name ( Name, getSrcLoc, nameUnique )
import NameSet
import RdrName ( RdrName )
-import TyCon ( tyConTyVars, tyConDataCons, tyConArity, newTyConRep,
+import TyCon ( tyConTyVars, tyConDataCons, tyConArity,
tyConTheta, maybeTyConSingleCon, isDataTyCon,
isEnumerationTyCon, isRecursiveTyCon, TyCon
)
import TcType ( TcType, ThetaType, mkTyVarTys, mkTyConApp, getClassPredTys_maybe,
isUnLiftedType, mkClassPred, tyVarsOfTypes, tcSplitFunTys,
- tcEqTypes, mkAppTys )
-import Type ( splitAppTys )
+ tcEqTypes, tcSplitAppTys, mkAppTys )
import Var ( TyVar, tyVarKind )
import VarSet ( mkVarSet, subVarSet )
import PrelNames
constraints = extra_constraints ++
[ mkClassPred clas [arg_ty]
| data_con <- tyConDataCons tycon,
- arg_ty <- dataConRepArgTys data_con,
+ arg_ty <- dataConRepArgTys data_con, -- dataConOrigArgTys???
-- Use the same type variables
-- as the type constructor,
-- hence no need to instantiate
= doptM Opt_GlasgowExts `thenM` \ gla_exts ->
if can_derive_via_isomorphism && (gla_exts || standard_instance) then
-- 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 { iDFunId = mk_dfun dfun_name,
iBinds = NewTypeDerived rep_tys }))
-- Want to drop 1 arg from (T s a) and (ST s a)
-- to get instance Monad (ST s) => Monad (T s)
- (tyvars, rep_ty) = newTyConRep tycon
- (rep_fn, rep_ty_args) = splitAppTys rep_ty
+ -- Note [newtype representation]
+ -- We must not use newTyConRep to get the representation
+ -- type, because that looks through all intermediate newtypes
+ -- To get the RHS of *this* newtype, just look at the data
+ -- constructor. 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!
+ tyvars = tyConTyVars tycon
+ rep_ty = head (dataConOrigArgTys (head (tyConDataCons 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 tyvars
pprInstInfo info = vcat [ptext SLIT("InstInfo:") <+> ppr (idType (iDFunId info))]
pprInstInfoDetails (InstInfo { iBinds = VanillaInst b _ }) = ppr b
-pprInstInfoDetails (InstInfo { iBinds = NewTypeDerived _}) = text "Derived from the represenation type"
+pprInstInfoDetails (InstInfo { iBinds = NewTypeDerived _}) = text "Derived from the representation type"
simpleInstInfoTy :: InstInfo -> Type
simpleInstInfoTy info = case tcSplitDFunTy (idType (iDFunId info)) of
tcSplitForAllTys, tcSplitPhiTy,
tcSplitFunTy_maybe, tcSplitFunTys, tcFunArgTy, tcFunResultTy,
tcSplitTyConApp, tcSplitTyConApp_maybe, tcTyConAppTyCon, tcTyConAppArgs,
- tcSplitAppTy_maybe, tcSplitAppTy, tcSplitSigmaTy,
+ tcSplitAppTy_maybe, tcSplitAppTy, tcSplitAppTys, tcSplitSigmaTy,
tcSplitMethodTy, tcGetTyVar_maybe, tcGetTyVar,
---------------------------------
import BasicTypes ( IPName(..), ipNameName )
import Unique ( Unique, Uniquable(..) )
import SrcLoc ( SrcLoc )
-import Util ( cmpList, thenCmp, equalLength )
+import Util ( cmpList, thenCmp, equalLength, snocView )
import Maybes ( maybeToBool, expectJust )
import Outputable
\end{code}
tcSplitAppTy_maybe (FunTy ty1 ty2) = Just (TyConApp funTyCon [ty1], ty2)
tcSplitAppTy_maybe (AppTy ty1 ty2) = Just (ty1, ty2)
tcSplitAppTy_maybe (NoteTy n ty) = tcSplitAppTy_maybe ty
-tcSplitAppTy_maybe (SourceTy (NType tc tys)) = tc_split_app tc tys
- --- Don't forget that newtype!
+tcSplitAppTy_maybe (SourceTy (NType tc tys)) = tc_split_app tc tys --- Don't forget that newtype!
tcSplitAppTy_maybe (TyConApp tc tys) = tc_split_app tc tys
tcSplitAppTy_maybe other = Nothing
-tc_split_app tc [] = Nothing
-tc_split_app tc tys = split tys []
- where
- split [ty2] acc = Just (TyConApp tc (reverse acc), ty2)
- split (ty:tys) acc = split tys (ty:acc)
+tc_split_app tc tys = case snocView tys of
+ Just (tys',ty') -> Just (TyConApp tc tys', ty')
+ Nothing -> Nothing
tcSplitAppTy ty = case tcSplitAppTy_maybe ty of
Just stuff -> stuff
Nothing -> pprPanic "tcSplitAppTy" (pprType ty)
+tcSplitAppTys :: Type -> (Type, [Type])
+tcSplitAppTys ty
+ = go ty []
+ where
+ go ty args = case tcSplitAppTy_maybe ty of
+ Just (ty', arg) -> go ty' (arg:args)
+ Nothing -> (ty,args)
+
tcGetTyVar_maybe :: Type -> Maybe TyVar
tcGetTyVar_maybe (TyVarTy tv) = Just tv
tcGetTyVar_maybe (NoteTy _ t) = tcGetTyVar_maybe t
| NewTyCon Type -- Newtype, with its *ultimate* representation type
-- By 'ultimate' I mean that the rep type is not itself
-- a newtype or type synonym.
-
+ -- The rep type isn't entirely simple:
+ -- for a recursive newtype we pick () as the rep type
+ -- newtype T = MkT T
+ --
-- The rep type has free type variables the tyConTyVars
-- Thus:
-- newtype T a = MkT [(a,Int)]
-- The rep type is [(a,Int)]
- --
- -- The rep type isn't entirely simple:
- -- for a recursive newtype we pick () as the rep type
- -- newtype T = MkT T
+ -- NB: the rep type isn't necessarily the original RHS of the
+ -- newtype decl, because the rep type looks through other
+ -- newtypes. If you want hte original RHS, look at the
+ -- argument type of the data constructor.
data DataConDetails datacon
= DataCons [datacon] -- Its data constructors, with fully polymorphic types
import SrcLoc ( noSrcLoc )
import PrimRep ( PrimRep(..) )
import Unique ( Uniquable(..) )
-import Util ( mapAccumL, seqList, lengthIs )
+import Util ( mapAccumL, seqList, lengthIs, snocView )
import Outputable
import UniqSet ( sizeUniqSet ) -- Should come via VarSet
import Maybe ( isJust )
splitAppTy_maybe (FunTy ty1 ty2) = Just (TyConApp funTyCon [ty1], ty2)
splitAppTy_maybe (AppTy ty1 ty2) = Just (ty1, ty2)
splitAppTy_maybe (NoteTy _ ty) = splitAppTy_maybe ty
-splitAppTy_maybe (SourceTy p) = splitAppTy_maybe (sourceTypeRep p)
-splitAppTy_maybe (TyConApp tc []) = Nothing
-splitAppTy_maybe (TyConApp tc tys) = split tys []
- where
- split [ty2] acc = Just (TyConApp tc (reverse acc), ty2)
- split (ty:tys) acc = split tys (ty:acc)
-
-splitAppTy_maybe other = Nothing
+splitAppTy_maybe (SourceTy p) = splitAppTy_maybe (sourceTypeRep p)
+splitAppTy_maybe (TyConApp tc tys) = case snocView tys of
+ Nothing -> Nothing
+ Just (tys',ty') -> Just (TyConApp tc tys', ty')
+splitAppTy_maybe other = Nothing
splitAppTy :: Type -> (Type, Type)
splitAppTy ty = case splitAppTy_maybe ty of
where
split orig_ty (AppTy ty arg) args = split ty ty (arg:args)
split orig_ty (NoteTy _ ty) args = split orig_ty ty args
- split orig_ty (SourceTy p) args = split orig_ty (sourceTypeRep p) args
+ split orig_ty (SourceTy p) args = split orig_ty (sourceTypeRep p) args
split orig_ty (FunTy ty1 ty2) args = ASSERT( null args )
(TyConApp funTyCon [], [ty1,ty2])
split orig_ty (TyConApp tc tc_args) args = (TyConApp tc [], tc_args ++ args)
nOfThem,
lengthExceeds, lengthIs, lengthAtLeast, listLengthCmp, atLength,
isSingleton, only,
- notNull,
+ notNull, snocView,
- snocView,
isIn, isn'tIn,
-- for-loop
notNull [] = False
notNull _ = True
+snocView :: [a] -> Maybe ([a],a)
+ -- Split off the last element
+snocView [] = Nothing
+snocView xs = go [] xs
+ where
+ -- Invariant: second arg is non-empty
+ go acc [x] = Just (reverse acc, x)
+ go acc (x:xs) = go (x:acc) xs
+
only :: [a] -> a
#ifdef DEBUG
only [a] = a
#endif
\end{code}
-\begin{code}
-snocView :: [a] -> ([a], a) -- Split off the last element
-snocView xs = go xs []
- where
- go [x] acc = (reverse acc, x)
- go (x:xs) acc = go xs (x:acc)
-\end{code}
-
Debugging/specialising versions of \tr{elem} and \tr{notElem}
\begin{code}