[commit: ghc] master: Liberalising IncoherentInstances (099f954)
git at git.haskell.org
git at git.haskell.org
Fri Aug 30 05:15:44 CEST 2013
Repository : ssh://git@git.haskell.org/ghc
On branch : master
Link : http://ghc.haskell.org/trac/ghc/changeset/099f9542e8ad2e38196de2be928ccbfaee545b44/ghc
>---------------------------------------------------------------
commit 099f9542e8ad2e38196de2be928ccbfaee545b44
Author: Joachim Breitner <mail at joachim-breitner.de>
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 <aseipp at pobox.com>
>---------------------------------------------------------------
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
More information about the ghc-commits
mailing list