import Util
import FastString
+import Data.List ( nubBy )
import Data.Maybe ( isJust )
\end{code}
pprEquation :: Equation -> SDoc
pprEquation (qtvs, pairs)
- = vcat [ptext SLIT("forall") <+> braces (pprWithCommas ppr (varSetElems qtvs)),
- nest 2 (vcat [ ppr t1 <+> ptext SLIT(":=:") <+> ppr t2 | (t1,t2) <- pairs])]
+ = vcat [ptext (sLit "forall") <+> braces (pprWithCommas ppr (varSetElems qtvs)),
+ nest 2 (vcat [ ppr t1 <+> ptext (sLit ":=:") <+> ppr t2 | (t1,t2) <- pairs])]
\end{code}
Given a bunch of predicates that must hold, such as
, not (instanceCantMatch inst_tcs trimmed_tcs)
, eqn <- checkClsFD qtvs fd cls_tvs tys_inst tys
, let p_inst = (mkClassPred cls tys_inst,
- ptext SLIT("arising from the instance declaration at")
+ ptext (sLit "arising from the instance declaration at")
<+> ppr (getSrcLoc ispec))
]
-> TyVarSet -> [Type] -- Proposed new instance type
-> [Instance]
badFunDeps cls_insts clas ins_tv_set ins_tys
- = [ ispec | fd <- fds, -- fds is often empty
+ = nubBy eq_inst $
+ [ ispec | fd <- fds, -- fds is often empty, so do this first!
let trimmed_tcs = trimRoughMatchTcs clas_tvs fd rough_tcs,
ispec@(Instance { is_tcs = inst_tcs, is_tvs = tvs,
is_tys = tys }) <- cls_insts,
where
(clas_tvs, fds) = classTvsFds clas
rough_tcs = roughMatchTcs ins_tys
+ eq_inst i1 i2 = instanceDFunId i1 == instanceDFunId i2
+ -- An single instance may appear twice in the un-nubbed conflict list
+ -- because it may conflict with more than one fundep. E.g.
+ -- class C a b c | a -> b, a -> c
+ -- instance C Int Bool Bool
+ -- instance C Int Char Char
+ -- The second instance conflicts with the first by *both* fundeps
trimRoughMatchTcs :: [TyVar] -> FunDep TyVar -> [Maybe Name] -> [Maybe Name]
-- Computing rough_tcs for a particular fundep