Repository : ssh://[email protected]/ghc On branch : master Link : http://ghc.haskell.org/trac/ghc/changeset/099f9542e8ad2e38196de2be928ccbfaee545b44/ghc
>--------------------------------------------------------------- commit 099f9542e8ad2e38196de2be928ccbfaee545b44 Author: Joachim Breitner <[email protected]> Date: Mon Aug 19 10:24:25 2013 +0200 Liberalising IncoherentInstances (Almost) as suggested by SPJ on http://www.haskell.org/pipermail/glasgow-haskell-users/2013-July/022651.html (fixes #8141) Signed-off-by: Austin Seipp <[email protected]> >--------------------------------------------------------------- 099f9542e8ad2e38196de2be928ccbfaee545b44 compiler/basicTypes/BasicTypes.lhs | 10 ++++----- compiler/types/InstEnv.lhs | 40 +++++++++++++++++++++++++++++++++++- docs/users_guide/glasgow_exts.xml | 4 +++- 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/compiler/basicTypes/BasicTypes.lhs b/compiler/basicTypes/BasicTypes.lhs index 838e368..877ee82 100644 --- a/compiler/basicTypes/BasicTypes.lhs +++ b/compiler/basicTypes/BasicTypes.lhs @@ -381,17 +381,17 @@ data OverlapFlag -- its ambiguous which to choose) | OverlapOk { isSafeOverlap :: Bool } - -- | Like OverlapOk, but also ignore this instance - -- if it doesn't match the constraint you are - -- trying to resolve, but could match if the type variables - -- in the constraint were instantiated + -- | Silently ignore this instance if you + -- find any other that matches the constraing you + -- are trying to resolve, including when checking if there are instances that + -- do not match, but unify. -- -- Example: constraint (Foo [b]) -- instances (Foo [Int]) Incoherent -- (Foo [a]) -- Without the Incoherent flag, we'd complain that -- instantiating 'b' would change which instance - -- was chosen + -- was chosen. | Incoherent { isSafeOverlap :: Bool } deriving (Eq, Data, Typeable) diff --git a/compiler/types/InstEnv.lhs b/compiler/types/InstEnv.lhs index 31a1bfb..a3ade6b 100644 --- a/compiler/types/InstEnv.lhs +++ b/compiler/types/InstEnv.lhs @@ -535,7 +535,7 @@ lookupInstEnv' ie cls tys = find ((item, map (lookup_tv subst) tpl_tvs) : ms) us rest -- Does not match, so next check whether the things unify - -- See Note [Overlapping instances] above + -- See Note [Overlapping instances] and Note [Incoherent Instances] | Incoherent _ <- oflag = find ms us rest @@ -625,12 +625,19 @@ insert_overlapping new_item (item:items) -- Keep new one | old_beats_new = item : items -- Keep old one + | incoherent new_item = item : items -- note [Incoherent Instances] + -- Keep old one + | incoherent item = new_item : items + -- Keep new one | otherwise = item : insert_overlapping new_item items -- Keep both where new_beats_old = new_item `beats` item old_beats_new = item `beats` new_item + incoherent (inst, _) = case is_flag inst of Incoherent _ -> True + _ -> False + (instA, _) `beats` (instB, _) = overlap_ok && isJust (tcMatchTys (mkVarSet (is_tvs instB)) (is_tys instB) (is_tys instA)) @@ -646,6 +653,37 @@ insert_overlapping new_item (item:items) _ -> True \end{code} +Note [Incoherent Instances] +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The original motivation for incoherent instances was about the situation where +an instance would unify, but not match. That would be an error, unless the +unifying instances is marked as incoherent. Example: + + class C a b c where foo :: (a,b,c) + instance C [a] b Int + instance [incoherent] [Int] b c + instance [incoherent] C a Int c + +Thanks to the incoherent flags, + foo :: ([a],b,Int) +works: Only instance one matches, the others just unify, but are marked +incoherent. + +So I can write + (foo :: ([a],b,Int)) :: ([Int], Int, Int). +but if that works then I really want to be able to write + foo :: ([Int], Int, Int) +as well. Now all three instances from above match. None is more specific than +another, so none is ruled out by the normal overlapping rules. In order to +allow this, we now (Aug 2013) liberarate the meaning of Incoherent instances to +say: "An incoherent instances can be ignored if there is another matching +instances." This subsumes the ignore-incoheren-unify-logic. + +The implementation is in insert_overlapping, where we remove incoherent +instances if there are others. + + %************************************************************************ %* * diff --git a/docs/users_guide/glasgow_exts.xml b/docs/users_guide/glasgow_exts.xml index 6c4046e..9056804 100644 --- a/docs/users_guide/glasgow_exts.xml +++ b/docs/users_guide/glasgow_exts.xml @@ -4542,7 +4542,9 @@ So GHC rejects the program.</para> <para> If, however, you add the flag <option>-XIncoherentInstances</option>, GHC will instead pick (C), without complaining about -the problem of subsequent instantiations. +the problem of subsequent instantiations. In general, the flag +<option>-XIncoherentInstances</option> will cause GHC to ignore an instance if +there is another instance that matches the constraint. </para> <para> Notice that we gave a type signature to <literal>f</literal>, so GHC had to _______________________________________________ ghc-commits mailing list [email protected] http://www.haskell.org/mailman/listinfo/ghc-commits
