It's better to read it as: "if we know these, then we're going to know these"
\begin{code}
-{-# OPTIONS -w #-}
--- The above warning supression flag is a temporary kludge.
--- While working on this module you are encouraged to remove it and fix
--- any warnings in the module. See
--- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
--- for details
-
module FunDeps (
- Equation, pprEquation,
- oclose, grow, improveOne,
+ Equation, pprEquation,
+ oclose, improveFromInstEnv, improveFromAnother,
checkInstCoverage, checkFunDeps,
pprFundeps
) where
import Name
import Var
import Class
-import TcGadt
import TcType
+import Unify
import InstEnv
import VarSet
import VarEnv
import Outputable
import Util
+import FastString
+
+import Data.List ( nubBy )
import Data.Maybe ( isJust )
\end{code}
]
\end{code}
-Note [Growing the tau-tvs using constraints]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-(grow preds tvs) is the result of extend the set of tyvars tvs
- using all conceivable links from pred
-
-E.g. tvs = {a}, preds = {H [a] b, K (b,Int) c, Eq e}
-Then grow precs tvs = {a,b,c}
-
-All the type variables from an implicit parameter are added, whether or
-not they are mentioned in tvs; see Note [Implicit parameters and ambiguity]
-in TcSimplify.
-
-See also Note [Ambiguity] in TcSimplify
-
-\begin{code}
-grow :: [PredType] -> TyVarSet -> TyVarSet
-grow preds fixed_tvs
- | null preds = real_fixed_tvs
- | otherwise = loop real_fixed_tvs
- where
- -- Add the implicit parameters;
- -- see Note [Implicit parameters and ambiguity] in TcSimplify
- real_fixed_tvs = foldr unionVarSet fixed_tvs ip_tvs
-
- loop fixed_tvs
- | new_fixed_tvs `subVarSet` fixed_tvs = fixed_tvs
- | otherwise = loop new_fixed_tvs
- where
- new_fixed_tvs = foldl extend fixed_tvs non_ip_tvs
-
- extend fixed_tvs pred_tvs
- | fixed_tvs `intersectsVarSet` pred_tvs = fixed_tvs `unionVarSet` pred_tvs
- | otherwise = fixed_tvs
-
- (ip_tvs, non_ip_tvs) = partitionWith get_ip preds
- get_ip (IParam _ ty) = Left (tyVarsOfType ty)
- get_ip other = Right (tyVarsOfPred other)
-\end{code}
%************************************************************************
%* *
-- We usually act on an equation by instantiating the quantified type varaibles
-- to fresh type variables, and then calling the standard unifier.
+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
\begin{code}
type Pred_Loc = (PredType, SDoc) -- SDoc says where the Pred comes from
+improveFromInstEnv :: (Class -> [Instance])
+ -> Pred_Loc
+ -> [(Equation,Pred_Loc,Pred_Loc)]
+-- Improvement from top-level instances
+improveFromInstEnv _inst_env pred
+ = improveOne _inst_env pred [] -- TODO: Refactor to directly use instance_eqnd?
+
+
+improveFromAnother :: Pred_Loc
+ -> Pred_Loc
+ -> [(Equation, Pred_Loc, Pred_Loc)]
+-- Improvement from another local (given or wanted) constraint
+improveFromAnother pred1 pred2
+ = improveOne (\_ -> []) pred1 [pred2] -- TODO: Refactor to directly use pairwise_eqns?
+
+
improveOne :: (Class -> [Instance]) -- Gives instances for given class
-> Pred_Loc -- Do improvement triggered by this
-> [Pred_Loc] -- Current constraints
-- combined (for error messages)
-- Just do improvement triggered by a single, distinguised predicate
-improveOne inst_env pred@(IParam ip ty, _) preds
+improveOne _inst_env pred@(IParam ip ty, _) preds
= [ ((emptyVarSet, [(ty,ty2)]), pred, p2)
| p2@(IParam ip2 ty2, _) <- preds
, ip==ip2
, 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")
- <+> ppr (getSrcLoc ispec))
+ sep [ ptext (sLit "arising from the dependency") <+> quotes (pprFunDep fd)
+ , ptext (sLit "in the instance declaration at")
+ <+> ppr (getSrcLoc ispec)])
]
-improveOne inst_env eq_pred preds
+improveOne _ _ _
= []
-- tys2 = [Maybe t1, t2]
--
-- We can instantiate x to t1, and then we want to force
--- (Tree x) [t1/x] :=: t2
+-- (Tree x) [t1/x] ~ t2
--
-- This function is also used when matching two Insts (rather than an Inst
-- against an instance decl. In that case, qtvs is empty, and we are doing
-> 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
--- class C a b c | a -> b where ...
+-- class C a b c | a -> b where ...
-- For each instance .... => C ta tb tc
--- we want to match only on the types ta, tc; so our
+-- we want to match only on the type ta; so our
-- rough-match thing must similarly be filtered.
--- Hence, we Nothing-ise the tb type right here
-trimRoughMatchTcs clas_tvs (_,rtvs) mb_tcs
+-- Hence, we Nothing-ise the tb and tc types right here
+trimRoughMatchTcs clas_tvs (ltvs, _) mb_tcs
= zipWith select clas_tvs mb_tcs
where
- select clas_tv mb_tc | clas_tv `elem` rtvs = Nothing
- | otherwise = mb_tc
+ select clas_tv mb_tc | clas_tv `elem` ltvs = mb_tc
+ | otherwise = Nothing
\end{code}