%
+% (c) The University of Glasgow 2006
% (c) The GRASP/AQUA Project, Glasgow University, 1998
%
\section[TypeRep]{Type - friends' interface}
\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 TypeRep (
TyThing(..),
Type(..), TyNote(..), -- Representation visible
funTyCon,
-- Pretty-printing
- pprType, pprParendType, pprTyThingCategory,
- pprPred, pprTheta, pprThetaArrow, pprClassPred,
+ pprType, pprParendType, pprTypeApp,
+ pprTyThing, pprTyThingCategory,
+ pprPred, pprTheta, pprForAll, pprThetaArrow, pprClassPred,
- -- Re-export fromKind
+ -- Kinds
liftedTypeKind, unliftedTypeKind, openTypeKind,
- isLiftedTypeKind, isUnliftedTypeKind, isOpenTypeKind,
- mkArrowKind, mkArrowKinds,
+ argTypeKind, ubxTupleKind,
+ isLiftedTypeKindCon, isLiftedTypeKind,
+ mkArrowKind, mkArrowKinds, isCoercionKind,
+
+ -- Kind constructors...
+ liftedTypeKindTyCon, openTypeKindTyCon, unliftedTypeKindTyCon,
+ argTypeKindTyCon, ubxTupleKindTyCon,
+
+ -- And their names
+ unliftedTypeKindTyConName, openTypeKindTyConName,
+ ubxTupleKindTyConName, argTypeKindTyConName,
+ liftedTypeKindTyConName,
+
+ -- Super Kinds
+ tySuperKind, coSuperKind,
+ isTySuperKind, isCoSuperKind,
+ tySuperKindTyCon, coSuperKindTyCon,
+
pprKind, pprParendKind
) where
import {-# SOURCE #-} DataCon( DataCon, dataConName )
-- friends:
-import Kind
-import Var ( Var, Id, TyVar, tyVarKind )
-import VarSet ( TyVarSet )
-import Name ( Name, NamedThing(..), BuiltInSyntax(..), mkWiredInName )
-import OccName ( mkOccNameFS, tcName, parenSymOcc )
-import BasicTypes ( IPName, tupleParens )
-import TyCon ( TyCon, mkFunTyCon, tyConArity, tupleTyConBoxity, isTupleTyCon, isRecursiveTyCon, isNewTyCon )
-import Class ( Class )
+import Var
+import VarSet
+import Name
+import OccName
+import BasicTypes
+import TyCon
+import Class
-- others
-import PrelNames ( gHC_PRIM, funTyConKey, listTyConKey, parrTyConKey, hasKey )
+import PrelNames
import Outputable
\end{code}
TyVar
Type
- | PredTy -- A high level source type
- PredType -- ...can be expanded to a representation type...
+ | PredTy -- The type of evidence for a type predictate
+ PredType -- See Note [PredTy], and Note [Equality predicates]
+ -- NB: A PredTy (EqPred _ _) can appear only as the kind
+ -- of a coercion variable; never as the argument or result
+ -- of a FunTy (unlike ClassP, IParam)
| NoteTy -- A type with a note attached
TyNote
Type -- The expanded version
+type Kind = Type -- Invariant: a kind is always
+ -- FunTy k1 k2
+ -- or TyConApp PrimTyCon [...]
+ -- or TyVar kv (during inference only)
+ -- or ForAll ... (for top-level coercions)
+
+type SuperKind = Type -- Invariant: a super kind is always
+ -- TyConApp SuperKindTyCon ...
+
data TyNote = FTVNote TyVarSet -- The free type variables of the noted expression
\end{code}
-------------------------------------
- Source types
+ Note [PredTy]
A type of the form
PredTy p
data PredType
= ClassP Class [Type] -- Class predicate
| IParam (IPName Name) Type -- Implicit parameter
+ | EqPred Type Type -- Equality predicate (ty1 ~ ty2)
type ThetaType = [PredType]
\end{code}
function. If the argument has type (PredTy p) then the predicate p is
represented by evidence (a dictionary, for example, of type (predRepTy p).
+Note [Equality predicates]
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+ forall a b. (a ~ S b) => a -> b
+could be represented by
+ ForAllTy a (ForAllTy b (FunTy (PredTy (EqPred a (S b))) ...))
+OR
+ ForAllTy a (ForAllTy b (ForAllTy (c::PredTy (EqPred a (S b))) ...))
+
+The latter is what we do. (Unlike for class and implicit parameter
+constraints, which do use FunTy.)
+
+Reason:
+ * FunTy is always a *value* function
+ * ForAllTy is discarded at runtime
+
+We often need to make a "wildcard" (c::PredTy..). We always use the same
+name (wildCoVarName), since it's not mentioned.
+
%************************************************************************
%* *
| ATyCon TyCon
| AClass Class
-instance Outputable TyThing where
- ppr thing = pprTyThingCategory thing <+> quotes (ppr (getName thing))
+instance Outputable TyThing where
+ ppr = pprTyThing
+
+pprTyThing :: TyThing -> SDoc
+pprTyThing thing = pprTyThingCategory thing <+> quotes (ppr (getName thing))
pprTyThingCategory :: TyThing -> SDoc
pprTyThingCategory (ATyCon _) = ptext SLIT("Type constructor")
%************************************************************************
%* *
-\subsection{Wired-in type constructors
+ Wired-in type constructors
%* *
%************************************************************************
We define a few wired-in type constructors here to avoid module knots
\begin{code}
+--------------------------
+-- First the TyCons...
+
funTyCon = mkFunTyCon funTyConName (mkArrowKinds [argTypeKind, openTypeKind] liftedTypeKind)
-- You might think that (->) should have type (?? -> ? -> *), and you'd be right
-- But if we do that we get kind errors when saying
-- the kind sub-typing does. Sigh. It really only matters if you use (->) in
-- a prefix way, thus: (->) Int# Int#. And this is unusual.
-funTyConName = mkWiredInName gHC_PRIM
- (mkOccNameFS tcName FSLIT("(->)"))
- funTyConKey
- Nothing -- No parent object
- (ATyCon funTyCon) -- Relevant TyCon
- BuiltInSyntax
+
+tySuperKindTyCon = mkSuperKindTyCon tySuperKindTyConName
+coSuperKindTyCon = mkSuperKindTyCon coSuperKindTyConName
+
+liftedTypeKindTyCon = mkKindTyCon liftedTypeKindTyConName
+openTypeKindTyCon = mkKindTyCon openTypeKindTyConName
+unliftedTypeKindTyCon = mkKindTyCon unliftedTypeKindTyConName
+ubxTupleKindTyCon = mkKindTyCon ubxTupleKindTyConName
+argTypeKindTyCon = mkKindTyCon argTypeKindTyConName
+
+mkKindTyCon :: Name -> TyCon
+mkKindTyCon name = mkVoidPrimTyCon name tySuperKind 0
+
+--------------------------
+-- ... and now their names
+
+tySuperKindTyConName = mkPrimTyConName FSLIT("BOX") tySuperKindTyConKey tySuperKindTyCon
+coSuperKindTyConName = mkPrimTyConName FSLIT("COERCION") coSuperKindTyConKey coSuperKindTyCon
+liftedTypeKindTyConName = mkPrimTyConName FSLIT("*") liftedTypeKindTyConKey liftedTypeKindTyCon
+openTypeKindTyConName = mkPrimTyConName FSLIT("?") openTypeKindTyConKey openTypeKindTyCon
+unliftedTypeKindTyConName = mkPrimTyConName FSLIT("#") unliftedTypeKindTyConKey unliftedTypeKindTyCon
+ubxTupleKindTyConName = mkPrimTyConName FSLIT("(#)") ubxTupleKindTyConKey ubxTupleKindTyCon
+argTypeKindTyConName = mkPrimTyConName FSLIT("??") argTypeKindTyConKey argTypeKindTyCon
+funTyConName = mkPrimTyConName FSLIT("(->)") funTyConKey funTyCon
+
+mkPrimTyConName occ key tycon = mkWiredInName gHC_PRIM (mkOccNameFS tcName occ)
+ key
+ (ATyCon tycon)
+ BuiltInSyntax
+ -- All of the super kinds and kinds are defined in Prim and use BuiltInSyntax,
+ -- because they are never in scope in the source
+
+------------------
+-- We also need Kinds and SuperKinds, locally and in TyCon
+
+kindTyConType :: TyCon -> Type
+kindTyConType kind = TyConApp kind []
+
+liftedTypeKind = kindTyConType liftedTypeKindTyCon
+unliftedTypeKind = kindTyConType unliftedTypeKindTyCon
+openTypeKind = kindTyConType openTypeKindTyCon
+argTypeKind = kindTyConType argTypeKindTyCon
+ubxTupleKind = kindTyConType ubxTupleKindTyCon
+
+mkArrowKind :: Kind -> Kind -> Kind
+mkArrowKind k1 k2 = FunTy k1 k2
+
+mkArrowKinds :: [Kind] -> Kind -> Kind
+mkArrowKinds arg_kinds result_kind = foldr mkArrowKind result_kind arg_kinds
+
+tySuperKind, coSuperKind :: SuperKind
+tySuperKind = kindTyConType tySuperKindTyCon
+coSuperKind = kindTyConType coSuperKindTyCon
+
+isTySuperKind (NoteTy _ ty) = isTySuperKind ty
+isTySuperKind (TyConApp kc []) = kc `hasKey` tySuperKindTyConKey
+isTySuperKind other = False
+
+isCoSuperKind :: SuperKind -> Bool
+isCoSuperKind (NoteTy _ ty) = isCoSuperKind ty
+isCoSuperKind (TyConApp kc []) = kc `hasKey` coSuperKindTyConKey
+isCoSuperKind other = False
+
+-------------------
+-- Lastly we need a few functions on Kinds
+
+isLiftedTypeKindCon tc = tc `hasKey` liftedTypeKindTyConKey
+
+isLiftedTypeKind :: Kind -> Bool
+isLiftedTypeKind (TyConApp tc []) = isLiftedTypeKindCon tc
+isLiftedTypeKind other = False
+
+isCoercionKind :: Kind -> Bool
+-- All coercions are of form (ty1 ~ ty2)
+-- This function is here rather than in Coercion,
+-- because it's used in a knot-tied way to enforce invariants in Var
+isCoercionKind (NoteTy _ k) = isCoercionKind k
+isCoercionKind (PredTy (EqPred {})) = True
+isCoercionKind other = False
\end{code}
+
%************************************************************************
%* *
\subsection{The external interface}
pprType ty = ppr_type TopPrec ty
pprParendType ty = ppr_type TyConPrec ty
+pprTypeApp :: NamedThing a => a -> SDoc -> [Type] -> SDoc
+-- The first arg is the tycon; it's used to arrange printing infix
+-- if it looks like an operator
+-- Second arg is the pretty-printed tycon
+pprTypeApp tc pp_tc tys = ppr_type_app TopPrec (getName tc) pp_tc tys
+
------------------
pprPred :: PredType -> SDoc
pprPred (ClassP cls tys) = pprClassPred cls tys
pprPred (IParam ip ty) = ppr ip <> dcolon <> pprType ty
-
+pprPred (EqPred ty1 ty2) = sep [ppr ty1, nest 2 (ptext SLIT("~")), ppr ty2]
pprClassPred :: Class -> [Type] -> SDoc
-pprClassPred clas tys = parenSymOcc (getOccName clas) (ppr clas)
- <+> sep (map pprParendType tys)
+pprClassPred clas tys = ppr_type_app TopPrec (getName clas) (ppr clas) tys
pprTheta :: ThetaType -> SDoc
pprTheta theta = parens (sep (punctuate comma (map pprPred theta)))
------------------
-- OK, here's the main printer
+pprKind = pprType
+pprParendKind = pprParendType
+
ppr_type :: Prec -> Type -> SDoc
ppr_type p (TyVarTy tv) = ppr tv
-ppr_type p (PredTy pred) = braces (ppr pred)
+ppr_type p (PredTy pred) = ifPprDebug (ptext SLIT("<pred>")) <> (ppr pred)
ppr_type p (NoteTy other ty2) = ppr_type p ty2
ppr_type p (TyConApp tc tys) = ppr_tc_app p tc tys
ppr_forall_type :: Prec -> Type -> SDoc
ppr_forall_type p ty
= maybeParen p FunPrec $
- sep [pprForAll tvs, pprThetaArrow ctxt, pprType tau]
+ sep [pprForAll tvs, pprThetaArrow (ctxt1 ++ ctxt2), pprType tau]
where
- (tvs, rho) = split1 [] ty
- (ctxt, tau) = split2 [] rho
-
- split1 tvs (ForAllTy tv ty) = split1 (tv:tvs) ty
- split1 tvs (NoteTy _ ty) = split1 tvs ty
- split1 tvs ty = (reverse tvs, ty)
+ (tvs, ctxt1, rho) = split1 [] [] ty
+ (ctxt2, tau) = split2 [] rho
+
+ -- We need to be extra careful here as equality constraints will occur as
+ -- type variables with an equality kind. So, while collecting quantified
+ -- variables, we separate the coercion variables out and turn them into
+ -- equality predicates.
+ split1 tvs eqs (ForAllTy tv ty)
+ | isCoVar tv = split1 tvs (eq:eqs) ty
+ | otherwise = split1 (tv:tvs) eqs ty
+ where
+ PredTy eq = tyVarKind tv
+ split1 tvs eqs (NoteTy _ ty) = split1 tvs eqs ty
+ split1 tvs eqs ty = (reverse tvs, reverse eqs, ty)
split2 ps (NoteTy _ arg -- Rather a disgusting case
`FunTy` res) = split2 ps (arg `FunTy` res)
ppr_tc_app p tc [ty]
| tc `hasKey` listTyConKey = brackets (pprType ty)
| tc `hasKey` parrTyConKey = ptext SLIT("[:") <> pprType ty <> ptext SLIT(":]")
+ | tc `hasKey` liftedTypeKindTyConKey = ptext SLIT("*")
+ | tc `hasKey` unliftedTypeKindTyConKey = ptext SLIT("#")
+ | tc `hasKey` openTypeKindTyConKey = ptext SLIT("(?)")
+ | tc `hasKey` ubxTupleKindTyConKey = ptext SLIT("(#)")
+ | tc `hasKey` argTypeKindTyConKey = ptext SLIT("??")
+
ppr_tc_app p tc tys
| isTupleTyCon tc && tyConArity tc == length tys
= tupleParens (tupleTyConBoxity tc) (sep (punctuate comma (map pprType tys)))
| otherwise
- = maybeParen p TyConPrec $
- ppr_tc tc <+> sep (map (ppr_type TyConPrec) tys)
+ = ppr_type_app p (getName tc) (ppr_naked_tc tc) tys
+
+ppr_type_app :: Prec -> Name -> SDoc -> [Type] -> SDoc
+ppr_type_app p tc pp_tc tys
+ | is_sym_occ -- Print infix if possible
+ , [ty1,ty2] <- tys -- We know nothing of precedence though
+ = maybeParen p FunPrec (sep [ppr_type FunPrec ty1,
+ pp_tc <+> ppr_type FunPrec ty2])
+ | otherwise
+ = maybeParen p TyConPrec (hang paren_tc 2 (sep (map pprParendType tys)))
+ where
+ is_sym_occ = isSymOcc (getOccName tc)
+ paren_tc | is_sym_occ = parens pp_tc
+ | otherwise = pp_tc
ppr_tc :: TyCon -> SDoc
-ppr_tc tc = parenSymOcc (getOccName tc) (pp_nt_debug <> ppr tc)
+ppr_tc tc = parenSymOcc (getOccName tc) (ppr_naked_tc tc)
+
+ppr_naked_tc :: TyCon -> SDoc -- No brackets for SymOcc
+ppr_naked_tc tc
+ = pp_nt_debug <> ppr tc
where
pp_nt_debug | isNewTyCon tc = ifPprDebug (if isRecursiveTyCon tc
then ptext SLIT("<recnt>")