+Ordering
+~~~~~~~~
+@Insts@ are ordered by their class/type info, rather than by their
+unique. This allows the context-reduction mechanism to use standard finite
+maps to do their stuff.
+
+\begin{code}
+instance Ord Inst where
+ compare = cmpInst
+
+instance Eq Inst where
+ (==) i1 i2 = case i1 `cmpInst` i2 of
+ EQ -> True
+ other -> False
+
+cmpInst (Dict _ pred1 _) (Dict _ pred2 _) = (pred1 `compare` pred2)
+cmpInst (Dict _ _ _) other = LT
+
+cmpInst (Method _ _ _ _ _ _) (Dict _ _ _) = GT
+cmpInst (Method _ id1 tys1 _ _ _) (Method _ id2 tys2 _ _ _) = (id1 `compare` id2) `thenCmp` (tys1 `compare` tys2)
+cmpInst (Method _ _ _ _ _ _) other = LT
+
+cmpInst (LitInst _ lit1 ty1 _) (LitInst _ lit2 ty2 _) = (lit1 `compare` lit2) `thenCmp` (ty1 `compare` ty2)
+cmpInst (LitInst _ _ _ _) (FunDep _ _ _ _) = LT
+cmpInst (LitInst _ _ _ _) other = GT
+
+cmpInst (FunDep _ clas1 fds1 _) (FunDep _ clas2 fds2 _) = (clas1 `compare` clas2) `thenCmp` (fds1 `compare` fds2)
+cmpInst (FunDep _ _ _ _) other = GT
+
+-- and they can only have HsInt or HsFracs in them.
+\end{code}
+
+
+Selection
+~~~~~~~~~
+\begin{code}
+instLoc (Dict u pred loc) = loc
+instLoc (Method u _ _ _ _ loc) = loc
+instLoc (LitInst u lit ty loc) = loc
+instLoc (FunDep _ _ _ loc) = loc
+
+getDictPred_maybe (Dict _ p _) = Just p
+getDictPred_maybe _ = Nothing
+
+getMethodTheta_maybe (Method _ _ _ theta _ _) = Just theta
+getMethodTheta_maybe _ = Nothing
+
+getDictClassTys (Dict u (Class clas tys) _) = (clas, tys)
+
+getFunDeps (FunDep _ clas fds _) = Just (clas, fds)
+getFunDeps _ = Nothing
+
+getFunDepsOfLIE lie = catMaybes (map getFunDeps (lieToList lie))
+
+getIPsOfPred (IParam n ty) = [(n, ty)]
+getIPsOfPred _ = []
+getIPsOfTheta theta = concatMap getIPsOfPred theta
+
+getIPs (Dict u (IParam n ty) loc) = [(n, ty)]
+getIPs (Method u id _ theta t loc) = getIPsOfTheta theta
+getIPs _ = []
+
+getIPsOfLIE lie = concatMap getIPs (lieToList lie)
+
+getAllFunDeps (FunDep _ clas fds _) = fds
+getAllFunDeps inst = map (\(n,ty) -> ([], [ty])) (getIPs inst)
+
+getAllFunDepsOfLIE lie = concat (map getAllFunDeps (lieToList lie))
+
+tyVarsOfInst :: Inst -> TcTyVarSet
+tyVarsOfInst (Dict _ pred _) = tyVarsOfPred pred
+tyVarsOfInst (Method _ id tys _ _ _) = tyVarsOfTypes tys `unionVarSet` idFreeTyVars id
+ -- The id might have free type variables; in the case of
+ -- locally-overloaded class methods, for example
+tyVarsOfInst (LitInst _ _ ty _) = tyVarsOfType ty
+tyVarsOfInst (FunDep _ _ fds _)
+ = foldr unionVarSet emptyVarSet (map tyVarsOfFd fds)
+ where tyVarsOfFd (ts1, ts2) =
+ tyVarsOfTypes ts1 `unionVarSet` tyVarsOfTypes ts2
+
+tyVarsOfInsts insts
+ = foldr unionVarSet emptyVarSet (map tyVarsOfInst insts)
+
+tyVarsOfLIE lie
+ = foldr unionVarSet emptyVarSet (map tyVarsOfInst insts)
+ where insts = lieToList lie
+\end{code}
+
+Predicates
+~~~~~~~~~~
+\begin{code}
+isDict :: Inst -> Bool
+isDict (Dict _ _ _) = True
+isDict other = False
+
+isClassDict :: Inst -> Bool
+isClassDict (Dict _ (Class _ _) _) = True
+isClassDict other = False
+
+isMethod :: Inst -> Bool
+isMethod (Method _ _ _ _ _ _) = True
+isMethod other = False
+
+isMethodFor :: TcIdSet -> Inst -> Bool
+isMethodFor ids (Method uniq id tys _ _ loc) = id `elemVarSet` ids
+isMethodFor ids inst = False
+
+isTyVarDict :: Inst -> Bool
+isTyVarDict (Dict _ (Class _ tys) _) = all isTyVarTy tys
+isTyVarDict other = False
+
+isStdClassTyVarDict (Dict _ (Class clas [ty]) _)
+ = isStandardClass clas && isTyVarTy ty
+isStdClassTyVarDict other
+ = False
+
+notFunDep :: Inst -> Bool
+notFunDep (FunDep _ _ _ _) = False
+notFunDep other = True
+\end{code}
+
+Two predicates which deal with the case where class constraints don't
+necessarily result in bindings. The first tells whether an @Inst@
+must be witnessed by an actual binding; the second tells whether an
+@Inst@ can be generalised over.
+
+\begin{code}
+instBindingRequired :: Inst -> Bool
+instBindingRequired (Dict _ (Class clas _) _) = not (isNoDictClass clas)
+instBindingRequired (Dict _ (IParam _ _) _) = False
+instBindingRequired other = True
+
+instCanBeGeneralised :: Inst -> Bool
+instCanBeGeneralised (Dict _ (Class clas _) _) = not (isCcallishClass clas)
+instCanBeGeneralised other = True
+\end{code}
+
+