%
% (c) The University of Glasgow 2006
% (c) The GRASP/AQUA Project, Glasgow University, 19921998
%
\begin{code}
module BuildTyCl (
buildSynTyCon, buildAlgTyCon, buildDataCon,
buildClass,
mkAbstractTyConRhs, mkOpenDataTyConRhs,
mkNewTyConRhs, mkDataTyConRhs, setAssocFamilyPermutation
) where
#include "HsVersions.h"
import IfaceEnv
import DataCon
import Var
import VarSet
import BasicTypes
import Name
import MkId
import Class
import TyCon
import Type
import Coercion
import TcRnMonad
import Util ( count )
import Outputable
\end{code}
\begin{code}
buildSynTyCon :: Name -> [TyVar]
-> SynTyConRhs
-> Kind
-> Maybe (TyCon, [Type])
-> TcRnIf m n TyCon
buildSynTyCon tc_name tvs rhs@(OpenSynTyCon {}) rhs_kind _
= let
kind = mkArrowKinds (map tyVarKind tvs) rhs_kind
in
return $ mkSynTyCon tc_name kind tvs rhs NoParentTyCon
buildSynTyCon tc_name tvs rhs@(SynonymTyCon {}) rhs_kind mb_family
= do {
; tycon <- fixM (\ tycon_rec -> do
{ parent <- mkParentInfo mb_family tc_name tvs tycon_rec
; let { tycon = mkSynTyCon tc_name kind tvs rhs parent
; kind = mkArrowKinds (map tyVarKind tvs) rhs_kind
}
; return tycon
})
; return tycon
}
buildAlgTyCon :: Name -> [TyVar]
-> ThetaType
-> AlgTyConRhs
-> RecFlag
-> Bool
-> Bool
-> Maybe (TyCon, [Type])
-> TcRnIf m n TyCon
buildAlgTyCon tc_name tvs stupid_theta rhs is_rec want_generics gadt_syn
mb_family
= do {
; tycon <- fixM (\ tycon_rec -> do
{ parent <- mkParentInfo mb_family tc_name tvs tycon_rec
; let { tycon = mkAlgTyCon tc_name kind tvs stupid_theta rhs
parent is_rec want_generics gadt_syn
; kind = mkArrowKinds (map tyVarKind tvs) liftedTypeKind
}
; return tycon
})
; return tycon
}
mkParentInfo :: Maybe (TyCon, [Type])
-> Name -> [TyVar]
-> TyCon
-> TcRnIf m n TyConParent
mkParentInfo Nothing _ _ _ =
return NoParentTyCon
mkParentInfo (Just (family, instTys)) tc_name tvs rep_tycon =
do {
; co_tycon_name <- newImplicitBinder tc_name mkInstTyCoOcc
; let co_tycon = mkFamInstCoercion co_tycon_name tvs
family instTys rep_tycon
; return $ FamilyTyCon family instTys co_tycon
}
mkAbstractTyConRhs :: AlgTyConRhs
mkAbstractTyConRhs = AbstractTyCon
mkOpenDataTyConRhs :: AlgTyConRhs
mkOpenDataTyConRhs = OpenTyCon Nothing
mkDataTyConRhs :: [DataCon] -> AlgTyConRhs
mkDataTyConRhs cons
= DataTyCon {
data_cons = cons,
is_enum =
not (null cons) &&
all isNullarySrcDataCon cons
}
mkNewTyConRhs :: Name -> TyCon -> DataCon -> TcRnIf m n AlgTyConRhs
mkNewTyConRhs tycon_name tycon con
= do { co_tycon_name <- newImplicitBinder tycon_name mkNewTyCoOcc
; let co_tycon = mkNewTypeCoercion co_tycon_name tycon etad_tvs etad_rhs
cocon_maybe | all_coercions || isRecursiveTyCon tycon
= Just co_tycon
| otherwise
= Nothing
; traceIf (text "mkNewTyConRhs" <+> ppr cocon_maybe)
; return (NewTyCon { data_con = con,
nt_rhs = rhs_ty,
nt_etad_rhs = (etad_tvs, etad_rhs),
nt_co = cocon_maybe } ) }
where
all_coercions = True
tvs = tyConTyVars tycon
inst_con_ty = applyTys (dataConUserType con) (mkTyVarTys tvs)
rhs_ty = ASSERT( isFunTy inst_con_ty ) funArgTy inst_con_ty
etad_tvs :: [TyVar]
etad_rhs :: Type
(etad_tvs, etad_rhs) = eta_reduce (reverse tvs) rhs_ty
eta_reduce :: [TyVar]
-> Type
-> ([TyVar], Type)
eta_reduce (a:as) ty | Just (fun, arg) <- splitAppTy_maybe ty,
Just tv <- getTyVar_maybe arg,
tv == a,
not (a `elemVarSet` tyVarsOfType fun)
= eta_reduce as fun
eta_reduce tvs ty = (reverse tvs, ty)
setAssocFamilyPermutation :: [TyVar] -> TyThing -> TyThing
setAssocFamilyPermutation clas_tvs (ATyCon tc)
= ATyCon (setTyConArgPoss clas_tvs tc)
setAssocFamilyPermutation _clas_tvs other
= pprPanic "setAssocFamilyPermutation" (ppr other)
buildDataCon :: Name -> Bool
-> [StrictnessMark]
-> [Name]
-> [TyVar] -> [TyVar]
-> [(TyVar,Type)]
-> ThetaType
-> [Type] -> Type
-> TyCon
-> TcRnIf m n DataCon
buildDataCon src_name declared_infix arg_stricts field_lbls
univ_tvs ex_tvs eq_spec ctxt arg_tys res_ty rep_tycon
= do { wrap_name <- newImplicitBinder src_name mkDataConWrapperOcc
; work_name <- newImplicitBinder src_name mkDataConWorkerOcc
; let
stupid_ctxt = mkDataConStupidTheta rep_tycon arg_tys univ_tvs
data_con = mkDataCon src_name declared_infix
arg_stricts field_lbls
univ_tvs ex_tvs eq_spec ctxt
arg_tys res_ty rep_tycon
stupid_ctxt dc_ids
dc_ids = mkDataConIds wrap_name work_name data_con
; return data_con }
mkDataConStupidTheta :: TyCon -> [Type] -> [TyVar] -> [PredType]
mkDataConStupidTheta tycon arg_tys univ_tvs
| null stupid_theta = []
| otherwise = filter in_arg_tys stupid_theta
where
tc_subst = zipTopTvSubst (tyConTyVars tycon) (mkTyVarTys univ_tvs)
stupid_theta = substTheta tc_subst (tyConStupidTheta tycon)
arg_tyvars = tyVarsOfTypes arg_tys
in_arg_tys pred = not $ isEmptyVarSet $
tyVarsOfPred pred `intersectVarSet` arg_tyvars
\end{code}
\begin{code}
buildClass :: Bool
-> Name -> [TyVar] -> ThetaType
-> [FunDep TyVar]
-> [TyThing]
-> [(Name, DefMeth, Type)]
-> RecFlag
-> TcRnIf m n Class
buildClass no_unf class_name tvs sc_theta fds ats sig_stuff tc_isrec
= do { traceIf (text "buildClass")
; tycon_name <- newImplicitBinder class_name mkClassTyConOcc
; datacon_name <- newImplicitBinder class_name mkClassDataConOcc
; fixM (\ rec_clas -> do {
let { rec_tycon = classTyCon rec_clas
; op_tys = [ty | (_,_,ty) <- sig_stuff]
; op_names = [op | (op,_,_) <- sig_stuff]
; op_items = [ (mkDictSelId no_unf op_name rec_clas, dm_info)
| (op_name, dm_info, _) <- sig_stuff ] }
; let n_value_preds = count (not . isEqPred) sc_theta
all_value_preds = n_value_preds == length sc_theta
; sc_sel_names <- mapM (newImplicitBinder class_name . mkSuperDictSelOcc)
[1..n_value_preds]
; let sc_sel_ids = [mkDictSelId no_unf sc_name rec_clas | sc_name <- sc_sel_names]
; let use_newtype = (n_value_preds + length sig_stuff == 1) && all_value_preds
args = sc_sel_names ++ op_names
arg_tys = map mkPredTy sc_theta ++ op_tys
; dict_con <- buildDataCon datacon_name
False
(map (const NotMarkedStrict) args)
[]
tvs []
[] []
arg_tys
(mkTyConApp rec_tycon (mkTyVarTys tvs))
rec_tycon
; rhs <- if use_newtype
then mkNewTyConRhs tycon_name rec_tycon dict_con
else return (mkDataTyConRhs [dict_con])
; let { clas_kind = mkArrowKinds (map tyVarKind tvs) liftedTypeKind
; tycon = mkClassTyCon tycon_name clas_kind tvs
rhs rec_clas tc_isrec
; atTyCons = [tycon | ATyCon tycon <- ats]
; result = mkClass class_name tvs fds
sc_theta sc_sel_ids atTyCons
op_items tycon
}
; traceIf (text "buildClass" <+> ppr tycon)
; return result
})}
\end{code}
Note [Class newtypes and equality predicates]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider
class (a ~ F b) => C a b where
op :: a -> b
We cannot represent this by a newtype, even though it's not
existential, and there's only one value field, because we do
capture an equality predicate:
data C a b where
MkC :: forall a b. (a ~ F b) => (a->b) -> C a b
We need to access this equality predicate when we get passes a C
dictionary. See Trac #2238