X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2Ftypecheck%2FTcGenDeriv.lhs;h=2192531d3debec3ed80542fa637ddc49670812b5;hp=845feccf40ef90d2a92e5507f47096e1fe4933b1;hb=58521c72cec262496dabf5fffb057d25ab17a0f7;hpb=1c15bee5a8fc004c16693d7d7a2d95b442549b66 diff --git a/compiler/typecheck/TcGenDeriv.lhs b/compiler/typecheck/TcGenDeriv.lhs index 845fecc..2192531 100644 --- a/compiler/typecheck/TcGenDeriv.lhs +++ b/compiler/typecheck/TcGenDeriv.lhs @@ -23,7 +23,9 @@ module TcGenDeriv ( gen_Show_binds, gen_Data_binds, gen_Typeable_binds, - gen_Functor_binds, functorLikeTraverse, deepSubtypesContaining, + gen_Functor_binds, + FFoldType(..), functorLikeTraverse, + deepSubtypesContaining, foldDataConArgs, gen_Foldable_binds, gen_Traversable_binds, genAuxBind @@ -40,7 +42,6 @@ import Name import HscTypes import PrelInfo import PrelNames -import MkId import PrimOp import SrcLoc import TyCon @@ -48,6 +49,7 @@ import TcType import TysPrim import TysWiredIn import Type +import Var( TyVar ) import TypeRep import VarSet import State @@ -55,9 +57,7 @@ import Util import MonadUtils import Outputable import FastString -import OccName import Bag - import Data.List ( partition, intersperse ) \end{code} @@ -718,7 +718,7 @@ gen_Ix_binds loc tycon mk_qual a b c = noLoc $ mkBindStmt (nlVarPat c) (nlHsApp (nlHsVar range_RDR) - (nlTuple [nlHsVar a, nlHsVar b] Boxed)) + (mkLHsVarTuple [a,b])) ---------------- single_con_index @@ -740,11 +740,11 @@ gen_Ix_binds loc tycon ) plus_RDR ( genOpApp ( (nlHsApp (nlHsVar unsafeRangeSize_RDR) - (nlTuple [nlHsVar l, nlHsVar u] Boxed)) + (mkLHsVarTuple [l,u])) ) times_RDR (mk_index rest) ) mk_one l u i - = nlHsApps unsafeIndex_RDR [nlTuple [nlHsVar l, nlHsVar u] Boxed, nlHsVar i] + = nlHsApps unsafeIndex_RDR [mkLHsVarTuple [l,u], nlHsVar i] ------------------ single_con_inRange @@ -753,8 +753,7 @@ gen_Ix_binds loc tycon con_pat cs_needed] $ foldl1 and_Expr (zipWith3Equal "single_con_inRange" in_range as_needed bs_needed cs_needed) where - in_range a b c = nlHsApps inRange_RDR [nlTuple [nlHsVar a, nlHsVar b] Boxed, - nlHsVar c] + in_range a b c = nlHsApps inRange_RDR [mkLHsVarTuple [a,b], nlHsVar c] \end{code} %************************************************************************ @@ -832,9 +831,8 @@ gen_Read_binds get_fixity loc tycon _ -> [nlHsApp (nlHsVar choose_RDR) (nlList (map mk_pair nullary_cons))] - mk_pair con = nlTuple [nlHsLit (mkHsString (data_con_str con)), - result_expr con []] - Boxed + mk_pair con = mkLHsTupleExpr [nlHsLit (mkHsString (data_con_str con)), + result_expr con []] read_non_nullary_con data_con | is_infix = mk_parser infix_prec infix_stmts body @@ -1095,7 +1093,7 @@ gen_Typeable_binds loc tycon [nlWildPat] (nlHsApps mkTypeRep_RDR [tycon_rep, nlList []]) where - tycon_rep = nlHsVar mkTyConRep_RDR `nlHsApp` nlHsLit (mkHsString (showSDoc (ppr tycon))) + tycon_rep = nlHsVar mkTyConRep_RDR `nlHsApp` nlHsLit (mkHsString (showSDocOneLine (ppr tycon))) mk_typeOf_RDR :: TyCon -> RdrName -- Use the arity of the TyCon to make the right typeOfn function @@ -1139,13 +1137,18 @@ we generate dataTypeOf _ = $dT + dataCast1 = gcast1 -- If T :: * -> * + dataCast2 = gcast2 -- if T :: * -> * -> * + + \begin{code} gen_Data_binds :: SrcSpan -> TyCon -> (LHsBinds RdrName, -- The method bindings DerivAuxBinds) -- Auxiliary bindings gen_Data_binds loc tycon - = (listToBag [gfoldl_bind, gunfold_bind, toCon_bind, dataTypeOf_bind], + = (listToBag [gfoldl_bind, gunfold_bind, toCon_bind, dataTypeOf_bind] + `unionBags` gcast_binds, -- Auxiliary definitions: the data type and constructors MkTyCon tycon : map MkDataCon data_cons) where @@ -1197,13 +1200,31 @@ gen_Data_binds loc tycon [nlWildPat] (nlHsVar (mk_data_type_name tycon)) + ------------ gcast1/2 + tycon_kind = tyConKind tycon + gcast_binds | tycon_kind `eqKind` kind1 = mk_gcast dataCast1_RDR gcast1_RDR + | tycon_kind `eqKind` kind2 = mk_gcast dataCast2_RDR gcast2_RDR + | otherwise = emptyBag + mk_gcast dataCast_RDR gcast_RDR + = unitBag (mk_easy_FunBind loc dataCast_RDR [nlVarPat f_RDR] + (nlHsVar gcast_RDR `nlHsApp` nlHsVar f_RDR)) + + +kind1, kind2 :: Kind +kind1 = liftedTypeKind `mkArrowKind` liftedTypeKind +kind2 = liftedTypeKind `mkArrowKind` kind1 gfoldl_RDR, gunfold_RDR, toConstr_RDR, dataTypeOf_RDR, mkConstr_RDR, - mkDataType_RDR, conIndex_RDR, prefix_RDR, infix_RDR :: RdrName + mkDataType_RDR, conIndex_RDR, prefix_RDR, infix_RDR, + dataCast1_RDR, dataCast2_RDR, gcast1_RDR, gcast2_RDR :: RdrName gfoldl_RDR = varQual_RDR gENERICS (fsLit "gfoldl") gunfold_RDR = varQual_RDR gENERICS (fsLit "gunfold") toConstr_RDR = varQual_RDR gENERICS (fsLit "toConstr") dataTypeOf_RDR = varQual_RDR gENERICS (fsLit "dataTypeOf") +dataCast1_RDR = varQual_RDR gENERICS (fsLit "dataCast1") +dataCast2_RDR = varQual_RDR gENERICS (fsLit "dataCast2") +gcast1_RDR = varQual_RDR tYPEABLE (fsLit "gcast1") +gcast2_RDR = varQual_RDR tYPEABLE (fsLit "gcast2") mkConstr_RDR = varQual_RDR gENERICS (fsLit "mkConstr") mkDataType_RDR = varQual_RDR gENERICS (fsLit "mkDataType") conIndex_RDR = varQual_RDR gENERICS (fsLit "constrIndex") @@ -1215,7 +1236,10 @@ infix_RDR = dataQual_RDR gENERICS (fsLit "Infix") %************************************************************************ %* * - Functor instances + Functor instances + + see http://www.mail-archive.com/haskell-prime@haskell.org/msg02116.html + %* * %************************************************************************ @@ -1240,10 +1264,10 @@ rather than just one level, as we typically do. What about types with more than one type parameter? In general, we only derive Functor for the last position: - data S a b = S1 [b] | S2 a + data S a b = S1 [b] | S2 (a, T a b) instance Functor (S a) where - fmap f (S1 bs) = S1 (fmap f bs) - fmap f (S2 a) = S2 a + fmap f (S1 bs) = S1 (fmap f bs) + fmap f (S2 (p,q)) = S2 (a, fmap f q) However, we have special cases for - tuples @@ -1280,27 +1304,27 @@ This is pretty much the same as $fmap, only without the $(cofmap 'a 'a) case: \begin{code} gen_Functor_binds :: SrcSpan -> TyCon -> (LHsBinds RdrName, DerivAuxBinds) gen_Functor_binds loc tycon - = (listToBag [fmap_bind], []) + = (unitBag fmap_bind, []) where data_cons = tyConDataCons tycon - arg = last (tyConTyVars tycon) -- argument to derive for, 'a in the above description fmap_bind = L loc $ mkFunBind (L loc fmap_RDR) (map fmap_eqn data_cons) fmap_eqn con = evalState (match_for_con [f_Pat] con parts) bs_RDRs - where parts = map derive_fmap_type (dataConOrigArgTys con) - - derive_fmap_type :: Type -> LHsExpr RdrName -> State [RdrName] (LHsExpr RdrName) - derive_fmap_type = functorLikeTraverse - (\ x -> return x) -- fmap f x = x - (\ x -> return (nlHsApp f_Expr x)) -- fmap f x = f x - (panic "contravariant") - (\g h x -> mkSimpleLam (\b -> h =<< (nlHsApp x `fmap` g b))) -- fmap f x = \b -> h (x (g b)) - (mkSimpleTupleCase match_for_con) -- fmap f x = case x of (a1,a2,..) -> (g1 a1,g2 a2,..) - (\_ g x -> do gg <- mkSimpleLam g - return $ nlHsApps fmap_RDR [gg,x]) -- fmap f x = fmap g x - (panic "in other argument") - (\_ g x -> g x) - arg + where + parts = foldDataConArgs ft_fmap con + + ft_fmap :: FFoldType (LHsExpr RdrName -> State [RdrName] (LHsExpr RdrName)) + -- Tricky higher order type; I can't say I fully understand this code :-( + ft_fmap = FT { ft_triv = \x -> return x -- fmap f x = x + , ft_var = \x -> return (nlHsApp f_Expr x) -- fmap f x = f x + , ft_fun = \g h x -> mkSimpleLam (\b -> h =<< (nlHsApp x `fmap` g b)) + -- fmap f x = \b -> h (x (g b)) + , ft_tup = mkSimpleTupleCase match_for_con -- fmap f x = case x of (a1,a2,..) -> (g1 a1,g2 a2,..) + , ft_ty_app = \_ g x -> do gg <- mkSimpleLam g -- fmap f x = fmap g x + return $ nlHsApps fmap_RDR [gg,x] + , ft_forall = \_ g x -> g x + , ft_bad_app = panic "in other argument" + , ft_co_var = panic "contravariant" } match_for_con = mkSimpleConMatch $ \con_name xsM -> do xs <- sequence xsM @@ -1314,19 +1338,27 @@ This function works like a fold: it makes a value of type 'a' in a bottom up way \begin{code} -- Generic traversal for Functor deriving -functorLikeTraverse :: a -- ^ Case: does not contain variable - -> a -- ^ Case: the variable itself - -> a -- ^ Case: the variable itself, contravariantly - -> (a -> a -> a) -- ^ Case: function type - -> (Boxity -> [a] -> a) -- ^ Case: tuple type - -> (Type -> a -> a) -- ^ Case: other tycon, variable only in last argument - -> a -- ^ Case: other tycon, variable only in last argument - -> (TcTyVar -> a -> a) -- ^ Case: forall type - -> TcTyVar -- ^ Variable to look for - -> Type -- ^ Type to process - -> a -functorLikeTraverse caseTrivial caseVar caseCoVar caseFun caseTuple caseTyApp caseWrongArg caseForAll var ty - = fst (go False ty) +data FFoldType a -- Describes how to fold over a Type in a functor like way + = FT { ft_triv :: a -- Does not contain variable + , ft_var :: a -- The variable itself + , ft_co_var :: a -- The variable itself, contravariantly + , ft_fun :: a -> a -> a -- Function type + , ft_tup :: Boxity -> [a] -> a -- Tuple type + , ft_ty_app :: Type -> a -> a -- Type app, variable only in last argument + , ft_bad_app :: a -- Type app, variable other than in last argument + , ft_forall :: TcTyVar -> a -> a -- Forall type + } + +functorLikeTraverse :: TyVar -- ^ Variable to look for + -> FFoldType a -- ^ How to fold + -> Type -- ^ Type to process + -> a +functorLikeTraverse var (FT { ft_triv = caseTrivial, ft_var = caseVar + , ft_co_var = caseCoVar, ft_fun = caseFun + , ft_tup = caseTuple, ft_ty_app = caseTyApp + , ft_bad_app = caseWrongArg, ft_forall = caseForAll }) + ty + = fst (go False ty) where -- go returns (result of type a, does type contain var) go co ty | Just ty' <- coreView ty = go co ty' go co (TyVarTy v) | v == var = (if co then caseCoVar else caseVar,True) @@ -1334,36 +1366,48 @@ functorLikeTraverse caseTrivial caseVar caseCoVar caseFun caseTuple caseTyApp ca go co (FunTy x y) | xc || yc = (caseFun xr yr,True) where (xr,xc) = go (not co) x (yr,yc) = go co y - go co (AppTy x y) | xc = (caseWrongArg,True) - | yc = (caseTyApp x yr,True) + go co (AppTy x y) | xc = (caseWrongArg, True) + | yc = (caseTyApp x yr, True) where (_, xc) = go co x (yr,yc) = go co y go co ty@(TyConApp con args) - | isTupleTyCon con = (caseTuple (tupleTyConBoxity con) xrs,True) - | null args = (caseTrivial,False) - | or (init xcs) = (caseWrongArg,True) - | (last xcs) = (caseTyApp (fst (splitAppTy ty)) (last xrs),True) + | isTupleTyCon con = (caseTuple (tupleTyConBoxity con) xrs,True) + | null args = (caseTrivial,False) -- T + | or (init xcs) = (caseWrongArg,True) -- T (..var..) ty + | last xcs = -- T (..no var..) ty + (caseTyApp (fst (splitAppTy ty)) (last xrs),True) where (xrs,xcs) = unzip (map (go co) args) go co (ForAllTy v x) | v /= var && xc = (caseForAll v xr,True) where (xr,xc) = go co x - go _ _ = (caseTrivial,False) - --- return all subtypes of ty that contain var somewhere --- these are the things that should appear in instance constraints -deepSubtypesContaining :: TcTyVar -> TcType -> [TcType] -deepSubtypesContaining = functorLikeTraverse - [] - [] - (panic "contravariant") - (\x y -> x ++ y) -- function - (\_ xs -> concat xs) -- tuple - (\ty x -> ty : x) -- tyapp - (panic "in other argument") - (\v x -> filter (not . (v `elemVarSet`) . tyVarsOfType) x) -- forall v - + go _ _ = (caseTrivial,False) + +-- Return all syntactic subterms of ty that contain var somewhere +-- These are the things that should appear in instance constraints +deepSubtypesContaining :: TyVar -> Type -> [TcType] +deepSubtypesContaining tv + = functorLikeTraverse tv + (FT { ft_triv = [] + , ft_var = [] + , ft_fun = (++), ft_tup = \_ xs -> concat xs + , ft_ty_app = (:) + , ft_bad_app = panic "in other argument" + , ft_co_var = panic "contravariant" + , ft_forall = \v xs -> filterOut ((v `elemVarSet`) . tyVarsOfType) xs }) + + +foldDataConArgs :: FFoldType a -> DataCon -> [a] +-- Fold over the arguments of the datacon +foldDataConArgs ft con + = map (functorLikeTraverse tv ft) (dataConOrigArgTys con) + where + tv = last (dataConUnivTyVars con) + -- Argument to derive for, 'a in the above description + -- The validity checks have ensured that con is + -- a vanilla data constructor -- Make a HsLam using a fresh variable from a State monad mkSimpleLam :: (LHsExpr id -> State [id] (LHsExpr id)) -> State [id] (LHsExpr id) +-- (mkSimpleLam fn) returns (\x. fn(x)) mkSimpleLam lam = do (n:names) <- get put names @@ -1398,7 +1442,10 @@ mkSimpleTupleCase match_for_con boxity insides x = do %************************************************************************ %* * - Foldable instances + Foldable instances + + see http://www.mail-archive.com/haskell-prime@haskell.org/msg02116.html + %* * %************************************************************************ @@ -1422,27 +1469,25 @@ since (f :: a -> b -> b), while (foldr f :: b -> t a -> b). \begin{code} gen_Foldable_binds :: SrcSpan -> TyCon -> (LHsBinds RdrName, DerivAuxBinds) gen_Foldable_binds loc tycon - = (listToBag [foldr_bind], []) + = (unitBag foldr_bind, []) where data_cons = tyConDataCons tycon - arg = last (tyConTyVars tycon) -- argument to derive for, 'a in the above description - foldr_bind = L loc $ mkFunBind (L loc foldr_RDR) (map foldr_eqn data_cons) + foldr_bind = L loc $ mkFunBind (L loc foldable_foldr_RDR) (map foldr_eqn data_cons) foldr_eqn con = evalState (match_for_con z_Expr [f_Pat,z_Pat] con parts) bs_RDRs - where parts = map derive_foldr_type (dataConOrigArgTys con) - - derive_foldr_type :: Type -> LHsExpr RdrName -> LHsExpr RdrName -> State [RdrName] (LHsExpr RdrName) - derive_foldr_type = functorLikeTraverse - (\ _ z -> return z) -- foldr f z x = z - (\ x z -> return (nlHsApps f_RDR [x,z])) -- foldr f z x = f x z - (panic "function") - (panic "function") - (\b gs x z -> mkSimpleTupleCase (match_for_con z) b gs x) - (\_ g x z -> do gg <- mkSimpleLam2 g -- foldr f z x = foldr (\xx zz -> g xx zz) z x - return $ nlHsApps foldable_foldr_RDR [gg,z,x]) - (panic "in other argument") - (\_ g x z -> g x z) - arg + where + parts = foldDataConArgs ft_foldr con + + ft_foldr :: FFoldType (LHsExpr RdrName -> LHsExpr RdrName -> State [RdrName] (LHsExpr RdrName)) + ft_foldr = FT { ft_triv = \_ z -> return z -- foldr f z x = z + , ft_var = \x z -> return (nlHsApps f_RDR [x,z]) -- foldr f z x = f x z + , ft_tup = \b gs x z -> mkSimpleTupleCase (match_for_con z) b gs x + , ft_ty_app = \_ g x z -> do gg <- mkSimpleLam2 g -- foldr f z x = foldr (\xx zz -> g xx zz) z x + return $ nlHsApps foldable_foldr_RDR [gg,z,x] + , ft_forall = \_ g x z -> g x z + , ft_co_var = panic "covariant" + , ft_fun = panic "function" + , ft_bad_app = panic "in other argument" } match_for_con z = mkSimpleConMatch (\_con_name -> foldrM ($) z) -- g1 v1 (g2 v2 (.. z)) \end{code} @@ -1450,7 +1495,9 @@ gen_Foldable_binds loc tycon %************************************************************************ %* * - Traversable instances + Traversable instances + + see http://www.mail-archive.com/haskell-prime@haskell.org/msg02116.html %* * %************************************************************************ @@ -1473,27 +1520,27 @@ instead of: traverse f (T x y) = T x <$> f y \begin{code} gen_Traversable_binds :: SrcSpan -> TyCon -> (LHsBinds RdrName, DerivAuxBinds) gen_Traversable_binds loc tycon - = (listToBag [traverse_bind], []) + = (unitBag traverse_bind, []) where data_cons = tyConDataCons tycon - arg = last (tyConTyVars tycon) -- argument to derive for, 'a in the above description traverse_bind = L loc $ mkFunBind (L loc traverse_RDR) (map traverse_eqn data_cons) traverse_eqn con = evalState (match_for_con [f_Pat] con parts) bs_RDRs - where parts = map derive_travese_type (dataConOrigArgTys con) - - derive_travese_type :: Type -> LHsExpr RdrName -> State [RdrName] (LHsExpr RdrName) - derive_travese_type = functorLikeTraverse - (\ x -> return (nlHsApps pure_RDR [x])) -- traverse f x = pure x - (\ x -> return (nlHsApps f_RDR [x])) -- travese f x = f x - (panic "function") - (panic "function") - (mkSimpleTupleCase match_for_con) -- travese f x z = case x of (a1,a2,..) -> (,,) <$> g1 a1 <*> g2 a2 <*> .. - (\_ g x -> do gg <- mkSimpleLam g -- travese f x = travese (\xx -> g xx) x - return $ nlHsApps traverse_RDR [gg,x]) - (panic "in other argument") - (\_ g x -> g x) - arg + where + parts = foldDataConArgs ft_trav con + + + ft_trav :: FFoldType (LHsExpr RdrName -> State [RdrName] (LHsExpr RdrName)) + ft_trav = FT { ft_triv = \x -> return (nlHsApps pure_RDR [x]) -- traverse f x = pure x + , ft_var = \x -> return (nlHsApps f_RDR [x]) -- travese f x = f x + , ft_tup = mkSimpleTupleCase match_for_con -- travese f x z = case x of (a1,a2,..) -> + -- (,,) <$> g1 a1 <*> g2 a2 <*> .. + , ft_ty_app = \_ g x -> do gg <- mkSimpleLam g -- travese f x = travese (\xx -> g xx) x + return $ nlHsApps traverse_RDR [gg,x] + , ft_forall = \_ g x -> g x + , ft_co_var = panic "covariant" + , ft_fun = panic "function" + , ft_bad_app = panic "in other argument" } match_for_con = mkSimpleConMatch $ \con_name xsM -> do xs <- sequence xsM @@ -1579,7 +1626,7 @@ genAuxBind loc (GenMaxTag tycon) genAuxBind loc (MkTyCon tycon) -- $dT = mkVarBind loc (mk_data_type_name tycon) ( nlHsVar mkDataType_RDR - `nlHsApp` nlHsLit (mkHsString (showSDoc (ppr tycon))) + `nlHsApp` nlHsLit (mkHsString (showSDocOneLine (ppr tycon))) `nlHsApp` nlList constrs ) where constrs = [nlHsVar (mk_constr_name con) | con <- tyConDataCons tycon]