[project @ 2004-02-24 17:13:56 by simonpj]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcSimplify.lhs
index 3bce567..db7e183 100644 (file)
@@ -77,6 +77,60 @@ import CmdLineOpts
 %************************************************************************
 
        --------------------------------------
+       Notes on functional dependencies (a bug)
+       --------------------------------------
+
+| > class Foo a b | a->b
+| >
+| > class Bar a b | a->b
+| >
+| > data Obj = Obj
+| >
+| > instance Bar Obj Obj
+| >
+| > instance (Bar a b) => Foo a b
+| >
+| > foo:: (Foo a b) => a -> String
+| > foo _ = "works"
+| >
+| > runFoo:: (forall a b. (Foo a b) => a -> w) -> w
+| > runFoo f = f Obj
+| 
+| *Test> runFoo foo
+| 
+| <interactive>:1:
+|     Could not deduce (Bar a b) from the context (Foo a b)
+|       arising from use of `foo' at <interactive>:1
+|     Probable fix:
+|         Add (Bar a b) to the expected type of an expression
+|     In the first argument of `runFoo', namely `foo'
+|     In the definition of `it': it = runFoo foo
+| 
+| Why all of the sudden does GHC need the constraint Bar a b? The
+| function foo didn't ask for that... 
+
+The trouble is that to type (runFoo foo), GHC has to solve the problem:
+
+       Given constraint        Foo a b
+       Solve constraint        Foo a b'
+
+Notice that b and b' aren't the same.  To solve this, just do
+improvement and then they are the same.  But GHC currently does
+       simplify constraints
+       apply improvement
+       and loop
+
+That is usually fine, but it isn't here, because it sees that Foo a b is
+not the same as Foo a b', and so instead applies the instance decl for
+instance Bar a b => Foo a b.  And that's where the Bar constraint comes
+from.
+
+The Right Thing is to improve whenever the constraint set changes at
+all.  Not hard in principle, but it'll take a bit of fiddling to do.  
+
+
+
+       --------------------------------------
                Notes on quantification
        --------------------------------------
 
@@ -306,6 +360,36 @@ but we'll produce the non-principal type
 
 
        --------------------------------------
+       The need for forall's in constraints
+       --------------------------------------
+
+[Exchange on Haskell Cafe 5/6 Dec 2000]
+
+  class C t where op :: t -> Bool
+  instance C [t] where op x = True
+
+  p y = (let f :: c -> Bool; f x = op (y >> return x) in f, y ++ [])
+  q y = (y ++ [], let f :: c -> Bool; f x = op (y >> return x) in f)
+
+The definitions of p and q differ only in the order of the components in
+the pair on their right-hand sides.  And yet:
+
+  ghc and "Typing Haskell in Haskell" reject p, but accept q;
+  Hugs rejects q, but accepts p;
+  hbc rejects both p and q;
+  nhc98 ... (Malcolm, can you fill in the blank for us!).
+
+The type signature for f forces context reduction to take place, and
+the results of this depend on whether or not the type of y is known,
+which in turn depends on which component of the pair the type checker
+analyzes first.  
+
+Solution: if y::m a, float out the constraints
+       Monad m, forall c. C (m c)
+When m is later unified with [], we can solve both constraints.
+
+
+       --------------------------------------
                Notes on implicit parameters
        --------------------------------------
 
@@ -1923,43 +2007,39 @@ tcSimplifyDeriv tyvars theta
     doptM Opt_AllowUndecidableInstances                `thenM` \ undecidable_ok ->
     let
        tv_set      = mkVarSet tvs
-       simpl_theta = map dictPred irreds       -- reduceMe squashes all non-dicts
-
-       check_pred pred
-         | isEmptyVarSet pred_tyvars   -- Things like (Eq T) should be rejected
-         = addErrTc (noInstErr pred)
-
-         | not undecidable_ok && not (isTyVarClassPred pred)
-         -- Check that the returned dictionaries are all of form (C a b)
-         --    (where a, b are type variables).  
-         -- We allow this if we had -fallow-undecidable-instances,
-         -- but note that risks non-termination in the 'deriving' context-inference
-         -- fixpoint loop.   It is useful for situations like
-         --    data Min h a = E | M a (h a)
-         -- which gives the instance decl
-         --    instance (Eq a, Eq (h a)) => Eq (Min h a)
-          = addErrTc (noInstErr pred)
+
+       (bad_insts, ok_insts) = partition is_bad_inst irreds
+       is_bad_inst dict 
+          = let pred = dictPred dict   -- reduceMe squashes all non-dicts
+            in isEmptyVarSet (tyVarsOfPred pred)
+                 -- Things like (Eq T) are bad
+            || (not undecidable_ok && not (isTyVarClassPred pred))
+                 -- The returned dictionaries should be of form (C a b)
+                 --    (where a, b are type variables).  
+                 -- We allow non-tyvar dicts if we had -fallow-undecidable-instances,
+                 -- but note that risks non-termination in the 'deriving' context-inference
+                 -- fixpoint loop.   It is useful for situations like
+                 --    data Min h a = E | M a (h a)
+                 -- which gives the instance decl
+                 --    instance (Eq a, Eq (h a)) => Eq (Min h a)
   
-         | not (pred_tyvars `subVarSet` tv_set) 
+       simpl_theta = map dictPred ok_insts
+       weird_preds = [pred | pred <- simpl_theta
+                           , not (tyVarsOfPred pred `subVarSet` tv_set)]  
          -- Check for a bizarre corner case, when the derived instance decl should
          -- have form  instance C a b => D (T a) where ...
          -- Note that 'b' isn't a parameter of T.  This gives rise to all sorts
          -- of problems; in particular, it's hard to compare solutions for
          -- equality when finding the fixpoint.  So I just rule it out for now.
-         = addErrTc (badDerivedPred pred)
   
-         | otherwise
-         = returnM ()
-         where
-           pred_tyvars = tyVarsOfPred pred
-
        rev_env = mkTopTyVarSubst tvs (mkTyVarTys tyvars)
                -- This reverse-mapping is a Royal Pain, 
                -- but the result should mention TyVars not TcTyVars
     in
    
-    mappM check_pred simpl_theta               `thenM_`
-    checkAmbiguity tvs simpl_theta tv_set      `thenM_`
+    addNoInstanceErrs Nothing [] bad_insts             `thenM_`
+    mapM_ (addErrTc . badDerivedPred) weird_preds      `thenM_`
+    checkAmbiguity tvs simpl_theta tv_set              `thenM_`
     returnM (substTheta rev_env simpl_theta)
   where
     doc    = ptext SLIT("deriving classes for a data type")
@@ -1977,7 +2057,7 @@ tcSimplifyDefault theta
   = newDicts DataDeclOrigin theta              `thenM` \ wanteds ->
     simpleReduceLoop doc reduceMe wanteds      `thenM` \ (frees, _, irreds) ->
     ASSERT( null frees )       -- try_me never returns Free
-    mappM (addErrTc . noInstErr) irreds        `thenM_`
+    addNoInstanceErrs Nothing []  irreds       `thenM_`
     if null irreds then
        returnM ()
     else
@@ -2169,8 +2249,6 @@ warnDefault dicts default_ty
                      pprInstsInFull tidy_dicts]
 
 -- Used for the ...Thetas variants; all top level
-noInstErr pred = ptext SLIT("No instance for") <+> quotes (ppr pred)
-
 badDerivedPred pred
   = vcat [ptext SLIT("Can't derive instances where the instance context mentions"),
          ptext SLIT("type variables that are not data type parameters"),