Check that AT instance is in a class
[ghc-hetmet.git] / compiler / types / Coercion.lhs
index cb85028..fb91a0d 100644 (file)
@@ -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...