module TcBinds ( tcBindsAndThen, tcPragmaSigs, checkSigTyVars, tcBindWithSigs, TcSigInfo(..) ) where
IMP_Ubiq()
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ <= 201
+IMPORT_DELOOPER(TcLoop) ( tcGRHSsAndBinds )
+#else
+import {-# SOURCE #-} TcGRHSs ( tcGRHSsAndBinds )
+#endif
import HsSyn ( HsBinds(..), Sig(..), MonoBinds(..),
Match, HsType, InPat(..), OutPat(..), HsExpr(..),
SYN_IE(RenamedMonoBinds)
)
import TcHsSyn ( SYN_IE(TcHsBinds), SYN_IE(TcMonoBinds),
- TcIdOcc(..), SYN_IE(TcIdBndr), SYN_IE(TcExpr),
+ SYN_IE(TcExpr),
tcIdType
)
import TcMonad
-import Inst ( Inst, SYN_IE(LIE), emptyLIE, plusLIE, InstOrigin(..),
- newDicts, tyVarsOfInst, instToId
+import Inst ( Inst, SYN_IE(LIE), emptyLIE, plusLIE, plusLIEs, InstOrigin(..),
+ newDicts, tyVarsOfInst, instToId, newMethodWithGivenTy
)
-import TcEnv ( tcExtendLocalValEnv, tcLookupLocalValueOK, newMonoIds,
+import TcEnv ( tcExtendLocalValEnv, tcLookupLocalValueOK, newLocalId,
tcGetGlobalTyVars, tcExtendGlobalTyVars
)
import SpecEnv ( SpecEnv )
-IMPORT_DELOOPER(TcLoop) ( tcGRHSsAndBinds )
import TcMatches ( tcMatchesFun )
import TcSimplify ( tcSimplify, tcSimplifyAndCheck )
import TcMonoType ( tcHsType )
import TcPat ( tcPat )
import TcSimplify ( bindInstsOfLocalFuns )
-import TcType ( SYN_IE(TcType), SYN_IE(TcThetaType), SYN_IE(TcTauType),
+import TcType ( TcIdOcc(..), SYN_IE(TcIdBndr),
+ SYN_IE(TcType), SYN_IE(TcThetaType), SYN_IE(TcTauType),
SYN_IE(TcTyVarSet), SYN_IE(TcTyVar),
- newTyVarTy, zonkTcType, zonkTcTyVar, zonkTcTyVars,
+ newTyVarTy, zonkTcType, zonkTcTheta, zonkSigTyVar,
newTcTyVar, tcInstSigType, newTyVarTys
)
import Unify ( unifyTauTy, unifyTauTyLists )
import Kind ( isUnboxedTypeKind, mkTypeKind, isTypeKind, mkBoxedTypeKind )
-import Id ( GenId, idType, mkUserLocal, mkUserId )
+import Id ( GenId, idType, mkUserId )
import IdInfo ( noIdInfo )
import Maybes ( maybeToBool, assocMaybe, catMaybes )
import Name ( getOccName, getSrcLoc, Name )
import Type ( mkTyVarTy, mkTyVarTys, isTyVarTy, tyVarsOfTypes, eqSimpleTheta,
mkSigmaTy, splitSigmaTy, mkForAllTys, mkFunTys, getTyVar, mkDictTy,
splitRhoTy, mkForAllTy, splitForAllTy )
-import TyVar ( GenTyVar, SYN_IE(TyVar), tyVarKind, minusTyVarSet, emptyTyVarSet,
+import TyVar ( GenTyVar, SYN_IE(TyVar), tyVarKind, mkTyVarSet, minusTyVarSet, emptyTyVarSet,
elementOfTyVarSet, unionTyVarSets, tyVarSetToList )
import Bag ( bagToList, foldrBag, isEmptyBag )
import Util ( isIn, zipEqual, zipWithEqual, zipWith3Equal, hasNoDups, assoc,
\begin{code}
tcBindsAndThen
- :: (TcHsBinds s -> thing -> thing) -- Combinator
+ :: (RecFlag -> TcMonoBinds s -> thing -> thing) -- Combinator
-> RenamedHsBinds
-> TcM s (thing, LIE s)
-> TcM s (thing, LIE s)
tcBindsAndThen combiner EmptyBinds do_next
= do_next `thenTc` \ (thing, lie) ->
- returnTc (combiner EmptyBinds thing, lie)
+ returnTc (combiner nonRecursive EmptyMonoBinds thing, lie)
tcBindsAndThen combiner (ThenBinds binds1 binds2) do_next
= tcBindsAndThen combiner binds1 (tcBindsAndThen combiner binds2 do_next)
-- All done
let
final_lie = lie2 `plusLIE` poly_lie
- final_binds = MonoBind poly_binds [] is_rec `ThenBinds`
- MonoBind inst_mbinds [] nonRecursive `ThenBinds`
- prag_binds
+ final_thing = combiner is_rec poly_binds $
+ combiner nonRecursive inst_mbinds $
+ combiner nonRecursive prag_binds
+ thing
in
- returnTc (prag_info_fn, (combiner final_binds thing, final_lie))
+ returnTc (prag_info_fn, (final_thing, final_lie))
) `thenTc` \ (_, result) ->
returnTc result
where
binder_names = map fst (bagToList (collectMonoBinders bind))
ty_sigs = [sig | sig@(Sig name _ _) <- sigs]
-
\end{code}
An aside. The original version of @tcBindsAndThen@ which lacks a
-- Create a new identifier for each binder, with each being given
-- a fresh unique, and a type-variable type.
- tcGetUniques no_of_binders `thenNF_Tc` \ uniqs ->
- mapNF_Tc mk_mono_id_ty binder_names `thenNF_Tc` \ mono_id_tys ->
+ -- For "mono_lies" see comments about polymorphic recursion at the
+ -- end of the function.
+ mapAndUnzipNF_Tc mk_mono_id binder_names `thenNF_Tc` \ (mono_lies, mono_ids) ->
let
- mono_id_tyvars = tyVarsOfTypes mono_id_tys
- mono_ids = zipWith3Equal "tcBindAndSigs" mk_id binder_names uniqs mono_id_tys
- mk_id name uniq ty = mkUserLocal (getOccName name) uniq ty (getSrcLoc name)
+ mono_lie = plusLIEs mono_lies
+ mono_id_tys = map idType mono_ids
in
-- TYPECHECK THE BINDINGS
-- The tyvars_not_to_gen are free in the environment, and hence
-- candidates for generalisation, but sometimes the monomorphism
-- restriction means we can't generalise them nevertheless
- getTyVarsToGen is_unrestricted mono_id_tyvars lie `thenTc` \ (tyvars_not_to_gen, tyvars_to_gen) ->
+ getTyVarsToGen is_unrestricted mono_id_tys lie `thenTc` \ (tyvars_not_to_gen, tyvars_to_gen) ->
-- DEAL WITH TYPE VARIABLE KINDS
- mapTc defaultUncommittedTyVar (tyVarSetToList tyvars_to_gen) `thenTc` \ tyvars_to_gen_list ->
- -- It's important that the final list (tyvars_to_gen_list) is fully
+ mapTc defaultUncommittedTyVar
+ (tyVarSetToList tyvars_to_gen) `thenTc` \ real_tyvars_to_gen_list ->
+ let
+ real_tyvars_to_gen = mkTyVarSet real_tyvars_to_gen_list
+ -- It's important that the final list
+ -- (real_tyvars_to_gen and real_tyvars_to_gen_list) is fully
-- zonked, *including boxity*, because they'll be included in the forall types of
-- the polymorphic Ids, and instances of these Ids will be generated from them.
+ --
+ -- Also NB that tcSimplify takes zonked tyvars as its arg, hence we pass
+ -- real_tyvars_to_gen
--
- -- This step can do unification => keep other zonking after this
+ -- **** This step can do unification => keep other zonking after this ****
+ in
-- SIMPLIFY THE LIE
tcExtendGlobalTyVars tyvars_not_to_gen (
if null tc_ty_sigs then
-- No signatures, so just simplify the lie
- tcSimplify tyvars_to_gen lie `thenTc` \ (lie_free, dict_binds, lie_bound) ->
+ -- NB: no signatures => no polymorphic recursion, so no
+ -- need to use mono_lies (which will be empty anyway)
+ tcSimplify real_tyvars_to_gen lie `thenTc` \ (lie_free, dict_binds, lie_bound) ->
returnTc (lie_free, dict_binds, map instToId (bagToList lie_bound))
else
- zonk_theta sig_theta `thenNF_Tc` \ sig_theta' ->
+ zonkTcTheta sig_theta `thenNF_Tc` \ sig_theta' ->
newDicts SignatureOrigin sig_theta' `thenNF_Tc` \ (dicts_sig, dict_ids) ->
-- It's important that sig_theta is zonked, because
-- dict_id is later used to form the type of the polymorphic thing,
-- and forall-types must be zonked so far as their bound variables
-- are concerned
+ let
+ -- The "givens" is the stuff available. We get that from
+ -- the context of the type signature, BUT ALSO the mono_lie
+ -- so that polymorphic recursion works right (see comments at end of fn)
+ givens = dicts_sig `plusLIE` mono_lie
+ in
+
-- Check that the needed dicts can be expressed in
-- terms of the signature ones
tcAddErrCtxt (sigsCtxt tysig_names) $
- tcSimplifyAndCheck tyvars_to_gen dicts_sig lie `thenTc` \ (lie_free, dict_binds) ->
+ tcSimplifyAndCheck real_tyvars_to_gen givens lie `thenTc` \ (lie_free, dict_binds) ->
returnTc (lie_free, dict_binds, dict_ids)
) `thenTc` \ (lie_free, dict_binds, dicts_bound) ->
- ASSERT( not (any (isUnboxedTypeKind . tyVarKind) tyvars_to_gen_list) )
+ ASSERT( not (any (isUnboxedTypeKind . tyVarKind) real_tyvars_to_gen_list) )
-- The instCantBeGeneralised stuff in tcSimplify should have
-- already raised an error if we're trying to generalise an unboxed tyvar
-- (NB: unboxed tyvars are always introduced along with a class constraint)
dict_tys = map tcIdType dicts_bound
mk_export binder_name mono_id zonked_mono_id_ty
- | maybeToBool maybe_sig = (sig_tyvars, TcId sig_poly_id, TcId mono_id)
- | otherwise = (tyvars_to_gen_list, TcId poly_id, TcId mono_id)
+ | maybeToBool maybe_sig = (sig_tyvars, TcId sig_poly_id, TcId mono_id)
+ | otherwise = (real_tyvars_to_gen_list, TcId poly_id, TcId mono_id)
where
maybe_sig = maybeSig tc_ty_sigs binder_name
Just (TySigInfo _ sig_poly_id sig_tyvars _ _ _) = maybe_sig
poly_id = mkUserId binder_name poly_ty (prag_info_fn binder_name)
- poly_ty = mkForAllTys tyvars_to_gen_list $ mkFunTys dict_tys $ zonked_mono_id_ty
+ poly_ty = mkForAllTys real_tyvars_to_gen_list $ mkFunTys dict_tys $ zonked_mono_id_ty
-- It's important to build a fully-zonked poly_ty, because
-- we'll slurp out its free type variables when extending the
-- local environment (tcExtendLocalValEnv); if it's not zonked
-- BUILD RESULTS
returnTc (
- AbsBinds tyvars_to_gen_list
+ AbsBinds real_tyvars_to_gen_list
dicts_bound
exports
(dict_binds `AndMonoBinds` mbind'),
where
no_of_binders = length binder_names
- mk_mono_id_ty binder_name = case maybeSig tc_ty_sigs binder_name of
- Just (TySigInfo name _ _ _ tau_ty _) -> returnNF_Tc tau_ty -- There's a signature
- otherwise -> newTyVarTy kind -- No signature
+ mk_mono_id binder_name
+ | theres_a_signature -- There's a signature; and it's overloaded,
+ && not (null sig_theta) -- so make a Method
+ = tcAddSrcLoc sig_loc $
+ newMethodWithGivenTy SignatureOrigin
+ (TcId poly_id) (mkTyVarTys sig_tyvars)
+ sig_theta sig_tau `thenNF_Tc` \ (mono_lie, TcId mono_id) ->
+ -- A bit turgid to have to strip the TcId
+ returnNF_Tc (mono_lie, mono_id)
+
+ | otherwise -- No signature or not overloaded;
+ = tcAddSrcLoc (getSrcLoc binder_name) $
+ (if theres_a_signature then
+ returnNF_Tc sig_tau -- Non-overloaded signature; use its type
+ else
+ newTyVarTy kind -- No signature; use a new type variable
+ ) `thenNF_Tc` \ mono_id_ty ->
+
+ newLocalId (getOccName binder_name) mono_id_ty `thenNF_Tc` \ mono_id ->
+ returnNF_Tc (emptyLIE, mono_id)
+ where
+ maybe_sig = maybeSig tc_ty_sigs binder_name
+ theres_a_signature = maybeToBool maybe_sig
+ Just (TySigInfo name poly_id sig_tyvars sig_theta sig_tau sig_loc) = maybe_sig
tysig_names = [name | (TySigInfo name _ _ _ _ _) <- tc_ty_sigs]
is_unrestricted = isUnRestrictedGroup tysig_names mbind
kind | is_rec = mkBoxedTypeKind -- Recursive, so no unboxed types
| otherwise = mkTypeKind -- Non-recursive, so we permit unboxed types
-
-zonk_theta theta = mapNF_Tc zonk theta
- where
- zonk (c,t) = zonkTcType t `thenNF_Tc` \ t' ->
- returnNF_Tc (c,t')
\end{code}
-@getImplicitStuffToGen@ decides what type variables generalise over.
+Polymorphic recursion
+~~~~~~~~~~~~~~~~~~~~~
+The game plan for polymorphic recursion in the code above is
+
+ * Bind any variable for which we have a type signature
+ to an Id with a polymorphic type. Then when type-checking
+ the RHSs we'll make a full polymorphic call.
+
+This fine, but if you aren't a bit careful you end up with a horrendous
+amount of partial application and (worse) a huge space leak. For example:
+
+ f :: Eq a => [a] -> [a]
+ f xs = ...f...
+
+If we don't take care, after typechecking we get
+
+ f = /\a -> \d::Eq a -> let f' = f a d
+ in
+ \ys:[a] -> ...f'...
+
+Notice the the stupid construction of (f a d), which is of course
+identical to the function we're executing. In this case, the
+polymorphic recursion ins't being used (but that's a very common case).
+
+This can lead to a massive space leak, from the following top-level defn:
+
+ ff :: [Int] -> [Int]
+ ff = f dEqInt
+
+Now (f dEqInt) evaluates to a lambda that has f' as a free variable; but
+f' is another thunk which evaluates to the same thing... and you end
+up with a chain of identical values all hung onto by the CAF ff.
+
+Solution: when typechecking the RHSs we always have in hand the
+*monomorphic* Ids for each binding. So we just need to make sure that
+if (Method f a d) shows up in the constraints emerging from (...f...)
+we just use the monomorphic Id. We achieve this by adding monomorphic Ids
+to the "givens" when simplifying constraints. Thats' what the "mono_lies"
+is doing.
+
+
+%************************************************************************
+%* *
+\subsection{getTyVarsToGen}
+%* *
+%************************************************************************
+
+@getTyVarsToGen@ decides what type variables generalise over.
For a "restricted group" -- see the monomorphism restriction
for a definition -- we bind no dictionaries, and
find which tyvars are constrained.
\begin{code}
-getTyVarsToGen is_unrestricted mono_tyvars lie
+getTyVarsToGen is_unrestricted mono_id_tys lie
= tcGetGlobalTyVars `thenNF_Tc` \ free_tyvars ->
- zonkTcTyVars mono_tyvars `thenNF_Tc` \ mentioned_tyvars ->
+ mapNF_Tc zonkTcType mono_id_tys `thenNF_Tc` \ zonked_mono_id_tys ->
let
- tyvars_to_gen = mentioned_tyvars `minusTyVarSet` free_tyvars
+ tyvars_to_gen = tyVarsOfTypes zonked_mono_id_tys `minusTyVarSet` free_tyvars
in
if is_unrestricted
then
tc_mono_binds bind@(PatMonoBind pat grhss_and_binds locn)
= tcAddSrcLoc locn $
+ tcAddErrCtxt (patMonoBindsCtxt bind) $
tcPat pat `thenTc` \ (pat2, lie_pat, pat_ty) ->
+
+ -- Before checking the RHS, but after the pattern, extend the envt with
+ -- bindings for the *polymorphic* Ids from any type signatures
tcExtendLocalValEnv sig_names sig_ids $
- tcGRHSsAndBinds grhss_and_binds `thenTc` \ (grhss_and_binds2, lie, grhss_ty) ->
- tcAddErrCtxt (patMonoBindsCtxt bind) $
- unifyTauTy pat_ty grhss_ty `thenTc_`
+ tcGRHSsAndBinds pat_ty grhss_and_binds `thenTc` \ (grhss_and_binds2, lie) ->
returnTc (PatMonoBind pat2 grhss_and_binds2 locn,
plusLIE lie_pat lie)
\end{code}
\begin{code}
data TcSigInfo s
- = TySigInfo Name
- (TcIdBndr s) -- *Polymorphic* binder for this value...
- [TcTyVar s] (TcThetaType s) (TcTauType s)
- SrcLoc
+ = TySigInfo
+ Name -- N, the Name in corresponding binding
+ (TcIdBndr s) -- *Polymorphic* binder for this value...
+ -- Usually has name = N, but doesn't have to.
+ [TcTyVar s]
+ (TcThetaType s)
+ (TcTauType s)
+ SrcLoc
maybeSig :: [TcSigInfo s] -> Name -> Maybe (TcSigInfo s)
checkSigMatch []
= returnTc (error "checkSigMatch")
-checkSigMatch tc_ty_sigs
- = -- CHECK THAT ALL THE SIGNATURE CONTEXTS ARE UNIFIABLE
+checkSigMatch tc_ty_sigs@( sig1@(TySigInfo _ id1 _ theta1 _ _) : all_sigs_but_first )
+ = -- CHECK THAT THE SIGNATURE TYVARS AND TAU_TYPES ARE OK
+ -- Doesn't affect substitution
+ mapTc check_one_sig tc_ty_sigs `thenTc_`
+
+ -- CHECK THAT ALL THE SIGNATURE CONTEXTS ARE UNIFIABLE
-- The type signatures on a mutually-recursive group of definitions
-- must all have the same context (or none).
--
-- We unify them because, with polymorphic recursion, their types
-- might not otherwise be related. This is a rather subtle issue.
-- ToDo: amplify
- tcAddErrCtxt (sigContextsCtxt tc_ty_sigs) (
- mapTc (unifyTauTyLists dict_tys1) dict_tys_s
- ) `thenTc_`
-
- -- CHECK THAT THE SIGNATURE TYVARS AND TAU_TYPES ARE OK
- -- Doesn't affect substitution
- mapTc check_one_sig tc_ty_sigs `thenTc_`
+ mapTc check_one_cxt all_sigs_but_first `thenTc_`
returnTc theta1
where
- (theta1:thetas) = [theta | TySigInfo _ _ _ theta _ _ <- tc_ty_sigs]
- (dict_tys1 : dict_tys_s) = map mk_dict_tys (theta1 : thetas)
- mk_dict_tys theta = [mkDictTy c t | (c,t) <- theta]
+ sig1_dict_tys = mk_dict_tys theta1
+ n_sig1_dict_tys = length sig1_dict_tys
+
+ check_one_cxt sig@(TySigInfo _ id _ theta _ src_loc)
+ = tcAddSrcLoc src_loc $
+ tcAddErrCtxt (sigContextsCtxt id1 id) $
+ checkTc (length this_sig_dict_tys == n_sig1_dict_tys)
+ sigContextsErr `thenTc_`
+ unifyTauTyLists sig1_dict_tys this_sig_dict_tys
+ where
+ this_sig_dict_tys = mk_dict_tys theta
check_one_sig (TySigInfo name id sig_tyvars _ sig_tau src_loc)
= tcAddSrcLoc src_loc $
tcAddErrCtxt (sigCtxt id) $
checkSigTyVars sig_tyvars sig_tau
+
+ mk_dict_tys theta = [mkDictTy c t | (c,t) <- theta]
\end{code}
-> TcM s ()
checkSigTyVars sig_tyvars sig_tau
- = tcGetGlobalTyVars `thenNF_Tc` \ globals ->
- let
- mono_tyvars = filter (`elementOfTyVarSet` globals) sig_tyvars
- in
- -- TEMPORARY FIX
- -- Until the final Bind-handling stuff is in, several type signatures in the same
- -- bindings group can cause the signature type variable from the different
- -- signatures to be unified. So we still need to zonk and check point (b).
- -- Remove when activating the new binding code
- mapNF_Tc zonkTcTyVar sig_tyvars `thenNF_Tc` \ sig_tys ->
- checkTcM (hasNoDups (map (getTyVar "checkSigTyVars") sig_tys))
+ = -- Several type signatures in the same bindings group can
+ -- cause the signature type variable from the different
+ -- signatures to be unified. So we need to zonk them.
+ mapNF_Tc zonkSigTyVar sig_tyvars `thenNF_Tc` \ sig_tyvars' ->
+
+ -- Point (a) is forced by the fact that they are signature type
+ -- variables, so the unifer won't bind them to a type.
+
+ -- Check point (b)
+ checkTcM (hasNoDups sig_tyvars')
(zonkTcType sig_tau `thenNF_Tc` \ sig_tau' ->
failTc (badMatchErr sig_tau sig_tau')
) `thenTc_`
-
-- Check point (c)
-- We want to report errors in terms of the original signature tyvars,
- -- ie sig_tyvars, NOT sig_tyvars'. sig_tys and sig_tyvars' correspond
+ -- ie sig_tyvars, NOT sig_tyvars'. sig_tyvars' correspond
-- 1-1 with sig_tyvars, so we can just map back.
- checkTc (null mono_tyvars)
- (notAsPolyAsSigErr sig_tau mono_tyvars)
+ tcGetGlobalTyVars `thenNF_Tc` \ globals ->
+ let
+-- mono_tyvars = [sig_tv | (sig_tv, sig_tv') <- sig_tyvars `zip` sig_tyvars',
+-- sig_tv' `elementOfTyVarSet` globals
+-- ]
+ mono_tyvars' = [sig_tv' | sig_tv' <- sig_tyvars',
+ sig_tv' `elementOfTyVarSet` globals]
+ in
+ checkTcM (null mono_tyvars')
+ (zonkTcType sig_tau `thenNF_Tc` \ sig_tau' ->
+ failTc (notAsPolyAsSigErr sig_tau' mono_tyvars'))
\end{code}
\begin{code}
tcPragmaSigs :: [RenamedSig] -- The pragma signatures
-> TcM s (Name -> PragmaInfo, -- Maps name to the appropriate PragmaInfo
- TcHsBinds s,
+ TcMonoBinds s,
LIE s)
-- For now we just deal with INLINE pragmas
-tcPragmaSigs sigs = returnTc (prag_fn, EmptyBinds, emptyLIE )
+tcPragmaSigs sigs = returnTc (prag_fn, EmptyMonoBinds, emptyLIE )
where
prag_fn name | any has_inline sigs = IWantToBeINLINEd
| otherwise = NoPragmaInfo
Here are the easy cases for tcPragmaSigs
\begin{code}
-tcPragmaSig (DeforestSig name loc)
- = returnTc ((name, addDeforestInfo DoDeforest),EmptyBinds,emptyLIE)
tcPragmaSig (InlineSig name loc)
= returnTc ((name, addUnfoldInfo (iWantToBeINLINEd UnfoldAlways)), EmptyBinds, emptyLIE)
tcPragmaSig (MagicUnfoldingSig name string loc)
-----------------------------------------------
notAsPolyAsSigErr sig_tau mono_tyvars sty
= hang (ptext SLIT("A type signature is more polymorphic than the inferred type"))
- 4 (vcat [text "Some type variables in the inferred type can't be forall'd, namely:",
- interpp'SP sty mono_tyvars,
- ptext SLIT("Possible cause: the RHS mentions something subject to the monomorphism restriction")
- ])
+ 4 (vcat [text "Can't for-all the type variable(s)" <+> interpp'SP sty mono_tyvars,
+ text "in the inferred type" <+> ppr sty sig_tau
+ ])
-----------------------------------------------
badMatchErr sig_ty inferred_ty sty
= sep [ptext SLIT("When checking signature(s) for:"), interpp'SP sty ids]
-----------------------------------------------
-sigContextsCtxt ty_sigs sty
- = hang (ptext SLIT("When matching the contexts of the signatures of a recursive group"))
- 4 (vcat (map ppr_tc_ty_sig ty_sigs))
- where
- ppr_tc_ty_sig (TySigInfo val _ tyvars theta tau_ty _)
- = hang ((<>) (ppr sty val) (ptext SLIT(" :: ")))
- 4 (if null theta
- then empty
- else hcat [parens (hsep (punctuate comma (map (ppr_inst sty) theta))),
- text " => ..."])
- ppr_inst sty (clas, ty) = hsep [ppr sty clas, ppr sty ty]
+sigContextsErr sty
+ = ptext SLIT("Mismatched contexts")
+sigContextsCtxt s1 s2 sty
+ = hang (hsep [ptext SLIT("When matching the contexts of the signatures for"),
+ ppr sty s1, ptext SLIT("and"), ppr sty s2])
+ 4 (ptext SLIT("(the signature contexts in a mutually recursive group should all be identical)"))
-----------------------------------------------
specGroundnessCtxt