[project @ 2001-03-25 13:29:54 by simonmar]
[ghc-hetmet.git] / ghc / compiler / types / FunDeps.lhs
index 6419d77..40e154f 100644 (file)
@@ -14,13 +14,14 @@ module FunDeps (
 
 import Var             ( TyVar )
 import Class           ( Class, FunDep, classTvsFds )
-import Type            ( Type, PredType(..), predTyUnique, tyVarsOfTypes, tyVarsOfPred )
+import Type            ( Type, ThetaType, PredType(..), predTyUnique, tyVarsOfTypes, tyVarsOfPred )
 import Subst           ( mkSubst, emptyInScopeSet, substTy )
-import Unify           ( unifyTyListsX )
+import Unify           ( unifyTyListsX, unifyExtendTysX )
 import Outputable      ( Outputable, SDoc, interppSP, ptext, empty, hsep, punctuate, comma )
 import VarSet
 import VarEnv
 import List            ( tails )
+import Maybes          ( maybeToBool )
 import ListSetOps      ( equivClassesByUniq )
 \end{code}
 
@@ -107,7 +108,7 @@ oclose preds fixed_tvs
        -- In our example, tv_fds will be [ ({x,y}, {z}), ({x,p},{q}) ]
        -- Meaning "knowing x,y fixes z, knowing x,p fixes q"
     tv_fds  = [ (tyVarsOfTypes xs, tyVarsOfTypes ys)
-             | Class cls tys <- preds,         -- Ignore implicit params
+             | ClassP cls tys <- preds,                -- Ignore implicit params
                let (cls_tvs, cls_fds) = classTvsFds cls,
                fd <- cls_fds,
                let (xs,ys) = instFD fd cls_tvs tys
@@ -142,8 +143,16 @@ grow preds fixed_tvs
 
 \begin{code}
 ----------
-type Equation = (Type,Type)    -- These two types should be equal
-                               -- INVARIANT: they aren't already equal
+type Equation = (TyVarSet, Type,Type)  -- These two types should be equal, for some
+                                       -- substitution of the tyvars in the tyvar set
+       -- For example, ({a,b}, (a,Int,b), (Int,z,Bool))
+       -- We unify z with Int, but since a and b are quantified we do nothing to them
+       -- We usually act on an equation by instantiating the quantified type varaibles
+       -- to fresh type variables, and then calling the standard unifier.
+       -- 
+       -- INVARIANT: they aren't already equal
+
+
 
 ----------
 improve :: InstEnv a           -- Gives instances for given class
@@ -199,13 +208,13 @@ checkGroup :: InstEnv a -> [PredType] -> [Equation]
 
 checkGroup inst_env (IParam _ ty : ips)
   =    -- For implicit parameters, all the types must match
-    [(ty, ty') | IParam _ ty' <- ips, ty /= ty']
+    [(emptyVarSet, ty, ty') | IParam _ ty' <- ips, ty /= ty']
 
-checkGroup inst_env clss@(Class cls tys : _)
+checkGroup inst_env clss@(ClassP cls tys : _)
   =    -- For classes life is more complicated  
        -- Suppose the class is like
        --      classs C as | (l1 -> r1), (l2 -> r2), ... where ...
-       -- Then FOR EACH PAIR (Class c tys1, Class c tys2) in the list clss
+       -- Then FOR EACH PAIR (ClassP c tys1, ClassP c tys2) in the list clss
        -- we check whether
        --      U l1[tys1/as] = U l2[tys2/as]
        --  (where U is a unifier)
@@ -223,25 +232,26 @@ checkGroup inst_env clss@(Class cls tys : _)
 
        -- NOTE that we iterate over the fds first; they are typically
        -- empty, which aborts the rest of the loop.
-    pairwise_eqns :: [(Type,Type)]
+    pairwise_eqns :: [Equation]
     pairwise_eqns      -- This group comes from pairwise comparison
       = [ eqn | fd <- cls_fds,
-               Class _ tys1 : rest <- tails clss,
-               Class _ tys2    <- rest,
+               ClassP _ tys1 : rest <- tails clss,
+               ClassP _ tys2   <- rest,
                eqn <- checkClsFD emptyVarSet fd cls_tvs tys1 tys2
        ]
 
-    instance_eqns :: [(Type,Type)]
+    instance_eqns :: [Equation]
     instance_eqns      -- This group comes from comparing with instance decls
       = [ eqn | fd <- cls_fds,
                (qtvs, tys1, _) <- cls_inst_env,
-               Class _ tys2    <- clss,
+               ClassP _ tys2    <- clss,
                eqn <- checkClsFD qtvs fd cls_tvs tys1 tys2
        ]
 
 
 ----------
-checkClsFD :: TyVarSet 
+checkClsFD :: TyVarSet                         -- The quantified type variables, which
+                                       -- can be instantiated to make the types match
           -> FunDep TyVar -> [TyVar]   -- One functional dependency from the class
           -> [Type] -> [Type]
           -> [Equation]
@@ -251,13 +261,16 @@ checkClsFD qtvs fd clas_tvs tys1 tys2
 -- unifyTyListsX will only bind variables in qtvs, so it's OK!
   = case unifyTyListsX qtvs ls1 ls2 of
        Nothing   -> []
-       Just unif -> [(sr1, sr2) | (r1,r2) <- rs1 `zip` rs2,
-                                  let sr1 = substTy full_unif r1,
-                                  let sr2 = substTy full_unif r2,
-                                  sr1 /= sr2]
+       Just unif -> [ (qtvs', substTy full_unif r1, substTy full_unif r2)
+                    | (r1,r2) <- rs1 `zip` rs2,
+                      not (maybeToBool (unifyExtendTysX qtvs unif r1 r2))]
                  where
                    full_unif = mkSubst emptyInScopeSet unif
                        -- No for-alls in sight; hmm
+
+                   qtvs' = filterVarSet (\v -> not (v `elemSubstEnv` unif)) qtvs
+                       -- qtvs' are the quantified type variables
+                       -- that have not been substituted out
   where
     (ls1, rs1) = instFD fd clas_tvs tys1
     (ls2, rs2) = instFD fd clas_tvs tys2
@@ -271,18 +284,18 @@ instFD (ls,rs) tvs tys
 \end{code}
 
 \begin{code}
-checkInstFDs :: Class -> [Type] -> Bool
+checkInstFDs :: ThetaType -> Class -> [Type] -> Bool
 -- Check that functional dependencies are obeyed in an instance decl
 -- For example, if we have 
---     class C a b | a -> b
+--     class theta => C a b | a -> b
 --     instance C t1 t2 
--- Then we require fv(t2) `subset` fv(t1)
+-- Then we require fv(t2) `subset` oclose(fv(t1), theta)
 
-checkInstFDs clas inst_taus
+checkInstFDs theta clas inst_taus
   = all fundep_ok fds
   where
     (tyvars, fds) = classTvsFds clas
-    fundep_ok fd  = tyVarsOfTypes rs `subVarSet` tyVarsOfTypes ls
+    fundep_ok fd  = tyVarsOfTypes rs `subVarSet` oclose theta (tyVarsOfTypes ls)
                 where
                   (ls,rs) = instFD fd tyvars inst_taus
 \end{code}