Repository : ssh://darcs.haskell.org//srv/darcs/ghc

On branch  : type-nats

http://hackage.haskell.org/trac/ghc/changeset/f557bf3c638759c434a11d367bcb1f91ee56afec

>---------------------------------------------------------------

commit f557bf3c638759c434a11d367bcb1f91ee56afec
Author: Iavor S. Diatchki <iavor.diatc...@gmail.com>
Date:   Tue Dec 25 21:05:09 2012 -0800

    Fixes to restore proper operation of widening function.
    
    We need to be careful when we use BRules in interaction:
    unlike axiom rules, using them does not always result in
    useful information---in fact often it results in trivial facts.
    
    Furthermore, we have to be careful not to disable an interaction
    with an existing assumption (i.e., if we apply a rule to bRule,
    we should also keep a copy around in case the same slot might
    be filled by an assumption).
    
    At present, we only interact the BRules after we've tried all assumptions:
    this reduces the number of useless facts we construct, but is sufficient
    for the main use case of interacting with BRules, namely improvements
    of the form: a + 0 ~ b => a ~ b.

>---------------------------------------------------------------

 compiler/typecheck/TcTypeNats.hs |   64 ++++++++++++++++++++++++++-----------
 1 files changed, 45 insertions(+), 19 deletions(-)

diff --git a/compiler/typecheck/TcTypeNats.hs b/compiler/typecheck/TcTypeNats.hs
index c2ac022..6c7bf8e 100644
--- a/compiler/typecheck/TcTypeNats.hs
+++ b/compiler/typecheck/TcTypeNats.hs
@@ -71,7 +71,7 @@ import TcSMonad ( TcS, emitInsoluble, setEvBind
 
 -- From base libraries
 import Data.Maybe ( isNothing, mapMaybe )
-import Data.List  ( sortBy, partition, find )
+import Data.List  ( sortBy, partition, find, nub )
 import Data.Ord   ( comparing )
 import Control.Monad ( msum, guard, when, liftM2 )
 import qualified Data.Set as S
@@ -658,7 +658,6 @@ funRule tc = AR
            | otherwise = natVars
 
 
-
 {- We get these when a rule fires.  Later, they are converted to
 givens or derived, depending on what we are doing. -}
 data RuleResult = RuleResult
@@ -666,13 +665,19 @@ data RuleResult = RuleResult
   , evidence         :: EvTerm  -- proof, given evidence for derived
   }
 
+instance Eq RuleResult where
+  r1 == r2  = eqType s1 t1 && eqType s2 t2
+    where (s1,s2) = conclusion r1
+          (t1,t2) = conclusion r2
+
 
 {- Check if the `ActiveRule` is completely instantiated and, if so,
 compute the resulting equation and the evidence for it.
 
-If some of the parameters for the equation were matched by
-`Derived` constraints, then the evidence for the term will be parmatereized
-by proofs for them.
+We also do some last effort solving: we check the ordering model to see
+if any ordering side-conditions are solvable now.  These never produe a
+new substitution (i.e., they have a yes/no answer) so we can just do
+them while attempting to fire the rule.
 -}
 fireRule :: LeqFacts -> ActiveRule -> Maybe RuleResult
 fireRule leq r =
@@ -799,16 +804,16 @@ setArg n (su,ev) r =
   inst xs = [ (x,apSimpSubst su y) | (x,y) <- xs ]
 
 -- Try to solve one of the assumptions by axiom or a basic rule.
-applyBasic1 :: ActiveRule -> Maybe ActiveRule
-applyBasic1 r = msum $ map attempt $ todoArgs r
+applyAxiom1 :: ActiveRule -> Maybe ActiveRule
+applyAxiom1 r = msum $ map attempt $ todoArgs r
   where
-  attempt (n,eq) = do (su,ev) <- byBasic eq
+  attempt (n,eq) = do (su,ev) <- byAxiom eq
                       return (setArg n (su, ev) r)
 
 -- Try to satisfy some of the rule's assumptions by axiom or a basic rule.
 -- We repeat the process until there no changes occur.
-applyBasic :: ActiveRule -> ActiveRule
-applyBasic r = maybe r applyBasic (applyBasic1 r)
+applyAxiom :: ActiveRule -> ActiveRule
+applyAxiom r = maybe r applyAxiom (applyAxiom1 r)
 
 {- The various ways in which an assumption fits the arguments of a rule.
 Note: currently, we use an assumption at most once per rule.
@@ -827,14 +832,33 @@ applyAsmp r ct =
            | otherwise  = id
 
 
+
+{- | Attempts to solve any remaining assumptions using bRules.
+Generally, interacting with `bRules` leads to trivially true facts,
+which is why we only do this once at the end.  The reason we do it
+at all is that it improves inferred types when comined with `funRule`s,
+resulting in improvements like this: (a + 0 ~ b) => (a ~ b)
+-}
+applyBRules :: ActiveRule -> ActiveRule
+applyBRules = attempt []
+  where
+  attempt tried r =
+    case filter ((`notElem` tried) . fst) (todoArgs r) of
+      [] -> r
+      (n,eq) : _ ->
+        case msum (map (`byBRule` eq) bRules) of
+          Just ok -> attempt tried (setArg n ok r)
+          Nothing -> attempt (n:tried) r
+
+
 {- Does forward reasoning:  compute new facts by interacting
 existing facts with a set of rules. -}
 interactActiveRules :: LeqFacts -> [ActiveRule] -> [Ct] -> [RuleResult]
 interactActiveRules leq rs0 cs0 =
-  loop (map applyBasic rs0) cs0
+  loop (map applyAxiom rs0) cs0
   where
-  loop rs []       = mapMaybe (fireRule leq) rs
-  loop rs (c : cs) = let new = map applyBasic (concatMap (`applyAsmp` c) rs)
+  loop rs []       = nub $ mapMaybe (fireRule leq . applyBRules) rs
+  loop rs (c : cs) = let new = map applyAxiom (concatMap (`applyAsmp` c) rs)
                      in loop (new ++ rs) cs
 
 {- A (possibly over-compliacted) example illustrating how the
@@ -953,25 +977,27 @@ customNat1Improvement leq ct
 -- Given a set of facts, apply forward reasoning using the "difficult"
 -- rules to derive some additional facts.
 widenAsmps :: [Ct] -> [Ct]
-widenAsmps asmps = step given wanted []
+widenAsmps asmps = step given wanted
 
   where
+  -- givens are already "widened", so we don't need to redo that part.
   (given, wanted) = partition isGivenCt asmps
 
   known c cs  = any (sameCt c) cs
 
-  step done [] [] = reverse done
-  step done [] cs = step done (reverse cs) []
-  step done (c : cs) ds
-    | known c done  = step done cs ds
+  step done [] = done
+  step done (c : cs)
+    | known c done  = step done cs
     | otherwise
       = let active = concatMap (`applyAsmp` c) $ map activate widenRules
             new = filter nonTrivial $
                   map (ruleResultToGiven (cc_loc c))
                       $ interactActiveRules leq active done
-        in step (c : done) cs (new ++ ds)
+        in step (c : done) (new ++ cs)
 
   -- For the moment, widedning rules have no ordering side conditions.
+  -- XXX: Actually, they do, the derived ordering rules have side conditions
+  -- so we should construct a model.
   leq = noLeqFacts
 
   nonTrivial ct = impossible ct || not (isEmptyUniqSet (tyVarsOfCt ct))



_______________________________________________
Cvs-ghc mailing list
Cvs-ghc@haskell.org
http://www.haskell.org/mailman/listinfo/cvs-ghc

Reply via email to