X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2Ftypes%2FCoercion.lhs;h=fb91a0de67d9d14d63e8e9d637e903c04e37aaee;hb=feb584b7ffd49827ff2b6e716965cfdcd344570e;hp=cb85028ce8add7c56b21664ff880f91476b7fc15;hpb=a7bda9e63ce091e4f33b6058a96686d7cde3d40d;p=ghc-hetmet.git diff --git a/compiler/types/Coercion.lhs b/compiler/types/Coercion.lhs index cb85028..fb91a0d 100644 --- a/compiler/types/Coercion.lhs +++ b/compiler/types/Coercion.lhs @@ -22,7 +22,7 @@ module Coercion ( mkSymCoercion, mkTransCoercion, mkLeftCoercion, mkRightCoercion, mkInstCoercion, mkAppCoercion, mkForAllCoercion, mkFunCoercion, mkInstsCoercion, mkUnsafeCoercion, - mkNewTypeCoercion, mkAppsCoercion, + mkNewTypeCoercion, mkDataInstCoercion, mkAppsCoercion, splitNewTypeRepCo_maybe, decomposeCo, @@ -37,12 +37,14 @@ import TypeRep import Type ( Type, Kind, PredType, substTyWith, mkAppTy, mkForAllTy, mkFunTy, splitAppTy_maybe, splitForAllTy_maybe, coreView, kindView, mkTyConApp, isCoercionKind, isEqPred, mkAppTys, - coreEqType, splitAppTys, isTyVarTy, splitTyConApp_maybe + coreEqType, splitAppTys, isTyVarTy, splitTyConApp_maybe, + tyVarsOfType, mkTyVarTys ) import TyCon ( TyCon, tyConArity, mkCoercionTyCon, isNewTyCon, newTyConRhs, newTyConCo, isCoercionTyCon, isCoercionTyCon_maybe ) import Var ( Var, TyVar, isTyVar, tyVarKind ) +import VarSet ( elemVarSet ) import Name ( BuiltInSyntax(..), Name, mkWiredInName, tcName ) import OccName ( mkOccNameFS ) import PrelNames ( symCoercionTyConKey, @@ -277,27 +279,74 @@ splitRightCoercion_maybe (TyConApp tc [co]) splitRightCoercion_maybe other = Nothing -- Unsafe coercion is not safe, it is used when we know we are dealing with --- bottom, which is the one case in which it is safe. It is also used to +-- bottom, which is one case in which it is safe. It is also used to -- implement the unsafeCoerce# primitive. mkUnsafeCoercion :: Type -> Type -> Coercion mkUnsafeCoercion ty1 ty2 = mkCoercion unsafeCoercionTyCon [ty1, ty2] --- Make the coercion associated with a newtype. If we have --- --- newtype T a b = MkT (Int, a, b) --- --- Then (mkNewTypeCoercion CoT T [a,b] (Int, a, b)) creates the coercion --- CoT, such kinding rule such that --- --- CoT S U :: (Int, S, U) :=: T S U +-- See note [Newtype coercions] in TyCon mkNewTypeCoercion :: Name -> TyCon -> [TyVar] -> Type -> TyCon mkNewTypeCoercion name tycon tvs rhs_ty = ASSERT (length tvs == tyConArity tycon) - mkCoercionTyCon name (tyConArity tycon) rule + mkCoercionTyCon name co_con_arity (mkKindingFun rule) where - rule args = mkCoKind (substTyWith tvs args rhs_ty) (TyConApp tycon args) + rule args = (TyConApp tycon tys, substTyWith tvs_eta tys rhs_eta, rest) + where + tys = take co_con_arity args + rest = drop co_con_arity args + + -- if the rhs_ty is a type application and it has a tail equal to a tail + -- of the tvs, then we eta-contract the type of the coercion + rhs_args = let (ty, ty_args) = splitAppTys rhs_ty in ty_args + + n_eta_tys = count_eta (reverse rhs_args) (reverse tvs) + + count_eta ((TyVarTy tv):rest_ty) (tv':rest_tv) + | tv == tv' && (not $ any (elemVarSet tv . tyVarsOfType) rest_ty) + -- if the last types are the same, and not free anywhere else + -- then eta contract + = 1 + (count_eta rest_ty rest_tv) + | otherwise -- don't + = 0 + count_eta _ _ = 0 + + + eqVar (TyVarTy tv) tv' = tv == tv' + eqVar _ _ = False + + co_con_arity = (tyConArity tycon) - n_eta_tys + + tvs_eta = (reverse (drop n_eta_tys (reverse tvs))) + + rhs_eta + | (ty, ty_args) <- splitAppTys rhs_ty + = mkAppTys ty (reverse (drop n_eta_tys (reverse ty_args))) + +-- Coercion identifying a data/newtype representation type and its family +-- instance. It has the form `Co tvs :: F ts :=: R tvs', where `Co' is the +-- coercion tycon built here, `F' the family tycon and `R' the (derived) +-- representation tycon. +-- +mkDataInstCoercion :: Name -- unique name for the coercion tycon + -> [TyVar] -- type parameters of the coercion (`tvs') + -> TyCon -- family tycon (`F') + -> [Type] -- type instance (`ts') + -> TyCon -- representation tycon (`R') + -> TyCon -- => coercion tycon (`Co') +mkDataInstCoercion name tvs family instTys rep_tycon + = mkCoercionTyCon name coArity (mkKindingFun rule) + where + coArity = length tvs + + rule args = (substTyWith tvs tys $ -- with sigma = [tys/tvs], + TyConApp family instTys, -- sigma (F ts) + TyConApp rep_tycon tys, -- :=: R tys + rest) -- surplus arguments + where + tys = take coArity args + rest = drop coArity args -------------------------------------- -- Coercion Type Constructors...