[project @ 1997-05-18 19:56:49 by sof]
[ghc-hetmet.git] / ghc / compiler / types / Type.lhs
index 41f3cce..0ae9b6d 100644 (file)
@@ -2,11 +2,12 @@
 #include "HsVersions.h"
 
 module Type (
-       GenType(..), Type(..), TauType(..),
+       GenType(..), SYN_IE(Type), SYN_IE(TauType),
        mkTyVarTy, mkTyVarTys,
        getTyVar, getTyVar_maybe, isTyVarTy,
-       mkAppTy, mkAppTys, splitAppTy,
-       mkFunTy, mkFunTys, splitFunTy, splitFunTyExpandingDicts,
+       mkAppTy, mkAppTys, splitAppTy, splitAppTys,
+       mkFunTy, mkFunTys,
+       splitFunTy, splitFunTyExpandingDicts, splitFunTyExpandingDictsAndPeeking,
        getFunTy_maybe, getFunTyExpandingDicts_maybe,
        mkTyConTy, getTyCon_maybe, applyTyCon,
        mkSynTy,
@@ -18,9 +19,9 @@ module Type (
 #endif
        isPrimType, isUnboxedType, typePrimRep,
 
-       RhoType(..), SigmaType(..), ThetaType(..),
+       SYN_IE(RhoType), SYN_IE(SigmaType), SYN_IE(ThetaType),
        mkDictTy,
-       mkRhoTy, splitRhoTy, mkTheta,
+       mkRhoTy, splitRhoTy, mkTheta, isDictTy,
        mkSigmaTy, splitSigmaTy,
 
        maybeAppTyCon, getAppTyCon,
@@ -36,46 +37,50 @@ module Type (
 
        isTauTy,
 
-       tyVarsOfType, tyVarsOfTypes, typeKind
+       tyVarsOfType, tyVarsOfTypes, namesOfType, typeKind,
+        showTypeCategory
     ) where
 
 IMP_Ubiq()
 IMPORT_DELOOPER(IdLoop)         -- for paranoia checking
-IMPORT_DELOOPER(TyLoop)         -- for paranoia checking
-IMPORT_DELOOPER(PrelLoop)  -- for paranoia checking
+IMPORT_DELOOPER(TyLoop)
+--IMPORT_DELOOPER(PrelLoop)  -- for paranoia checking
 
 -- friends:
-import Class   ( classSig, classOpLocalType, GenClass{-instances-} )
-import Kind    ( mkBoxedTypeKind, resultKind, notArrowKind )
-import TyCon   ( mkFunTyCon, mkTupleTyCon, isFunTyCon, isPrimTyCon, isDataTyCon, isSynTyCon,
+import Class   --( classSig, classOpLocalType, GenClass{-instances-} )
+import Kind    ( mkBoxedTypeKind, resultKind, notArrowKind, Kind )
+import TyCon   ( mkFunTyCon, isFunTyCon, isEnumerationTyCon, isTupleTyCon, maybeTyConSingleCon,
+                 isPrimTyCon, isDataTyCon, isSynTyCon, maybeNewTyCon, isNewTyCon,
                  tyConKind, tyConDataCons, getSynTyConDefn, TyCon )
-import TyVar   ( tyVarKind, GenTyVar{-instances-}, GenTyVarSet(..),
+import TyVar   ( tyVarKind, GenTyVar{-instances-}, SYN_IE(GenTyVarSet),
                  emptyTyVarSet, unionTyVarSets, minusTyVarSet,
-                 unitTyVarSet, nullTyVarEnv, lookupTyVarEnv,
-                 addOneToTyVarEnv, TyVarEnv(..) )
-import Usage   ( usageOmega, GenUsage, Usage(..), UVar(..), UVarEnv(..),
+                 unitTyVarSet, nullTyVarEnv, lookupTyVarEnv, delFromTyVarEnv,
+                 addOneToTyVarEnv, SYN_IE(TyVarEnv), SYN_IE(TyVar) )
+import Usage   ( usageOmega, GenUsage, SYN_IE(Usage), SYN_IE(UVar), SYN_IE(UVarEnv),
                  nullUVarEnv, addOneToUVarEnv, lookupUVarEnv, eqUVar,
                  eqUsage )
 
+import Name    ( NamedThing(..), 
+                 NameSet(..), unionNameSets, emptyNameSet, unitNameSet, minusNameSet
+               )
+
 -- others
 import Maybes  ( maybeToBool, assocMaybe )
 import PrimRep ( PrimRep(..) )
 import Unique  -- quite a few *Keys
+import UniqFM   ( Uniquable(..) )
 import Util    ( thenCmp, zipEqual, assoc,
-                 panic, panic#, assertPanic, pprTrace{-ToDo:rm-}, pprPanic{-ToDo:rm-},
+                 panic, panic#, assertPanic, pprPanic,
                  Ord3(..){-instances-}
                )
 -- ToDo:rm all these
-import {-mumble-}
-       Pretty
-import  {-mumble-}
-       PprStyle
-import {-mumble-}
-       PprType --(pprType )
-import  {-mumble-}
-       UniqFM (ufmToList )
-import {-mumble-}
-       Outputable
+--import       {-mumble-}
+--     Pretty
+--import  {-mumble-}
+--     PprStyle
+--import       {-mumble-}
+--     PprType --(pprType )
+--import PprEnv
 \end{code}
 
 Data types
@@ -134,6 +139,21 @@ type SigmaType = Type
 \end{code}
 
 
+Notes on type synonyms
+~~~~~~~~~~~~~~~~~~~~~~
+The various "split" functions (splitFunTy, splitRhoTy, splitForAllTy) try
+to return type synonyms whereever possible. Thus
+
+       type Foo a = a -> a
+
+we want 
+       splitFunTys (a -> Foo a) = ([a], Foo a)
+not                               ([a], a -> a)
+
+The reason is that we then get better (shorter) type signatures in 
+interfaces.  Notably this plays a role in tcTySigs in TcBinds.lhs.
+
+
 Expand abbreviations
 ~~~~~~~~~~~~~~~~~~~~
 Removes just the top level of any abbreviations.
@@ -156,7 +176,7 @@ expandTy (DictTy clas ty u)
                -- no methods!
 
        other -> ASSERT(not (null all_arg_tys))
-               foldl AppTy (TyConTy (mkTupleTyCon (length all_arg_tys)) u) all_arg_tys
+               foldl AppTy (TyConTy (tupleTyCon (length all_arg_tys)) u) all_arg_tys
 
                -- A tuple of 'em
                -- Note: length of all_arg_tys can be 0 if the class is
@@ -203,8 +223,13 @@ mkAppTy = AppTy
 mkAppTys :: GenType t u -> [GenType t u] -> GenType t u
 mkAppTys t ts = foldl AppTy t ts
 
-splitAppTy :: GenType t u -> (GenType t u, [GenType t u])
-splitAppTy t = go t []
+splitAppTy :: GenType t u -> (GenType t u, GenType t u)
+splitAppTy (AppTy t arg) = (t,arg)
+splitAppTy (SynTy _ _ t) = splitAppTy t
+splitAppTy other        = panic "splitAppTy"
+
+splitAppTys :: GenType t u -> (GenType t u, [GenType t u])
+splitAppTys t = go t []
   where
     go (AppTy t arg)     ts = go t (arg:ts)
     go (FunTy fun arg u) ts = (TyConTy mkFunTyCon u, fun:arg:ts)
@@ -227,25 +252,66 @@ mkFunTys ts t = foldr (\ f a -> FunTy f a usageOmega) t ts
   -- ToDo: NUKE when we do dicts via newtype
 
 getFunTy_maybe :: GenType t u -> Maybe (GenType t u, GenType t u)
-getFunTy_maybe (FunTy arg result _) = Just (arg,result)
-getFunTy_maybe (AppTy (AppTy (TyConTy tycon _) arg) res)
+getFunTy_maybe t
+  = go t t
+  where 
+       -- See notes on type synonyms above
+    go syn_t (FunTy arg result _) = Just (arg,result)
+    go syn_t (AppTy (AppTy (TyConTy tycon _) arg) res)
                 | isFunTyCon tycon = Just (arg, res)
-getFunTy_maybe (SynTy _ _ t)        = getFunTy_maybe t
-getFunTy_maybe other               = Nothing
+    go syn_t (SynTy _ _ t)          = go syn_t t
+    go syn_t other                 = Nothing
 
-getFunTyExpandingDicts_maybe :: Type -> Maybe (Type, Type)
-getFunTyExpandingDicts_maybe (FunTy arg result _) = Just (arg,result)
-getFunTyExpandingDicts_maybe
-       (AppTy (AppTy (TyConTy tycon _) arg) res) | isFunTyCon tycon = Just (arg, res)
-getFunTyExpandingDicts_maybe (SynTy _ _ t)        = getFunTyExpandingDicts_maybe t
-getFunTyExpandingDicts_maybe ty@(DictTy _ _ _)   = getFunTyExpandingDicts_maybe (expandTy ty)
-getFunTyExpandingDicts_maybe other               = Nothing
-
-splitFunTy              :: GenType t u -> ([GenType t u], GenType t u)
-splitFunTyExpandingDicts :: Type       -> ([Type], Type)
+getFunTyExpandingDicts_maybe :: Bool -- True <=> peek inside newtype applicatons
+                            -> Type
+                            -> Maybe (Type, Type)
 
-splitFunTy              t = split_fun_ty getFunTy_maybe               t
-splitFunTyExpandingDicts t = split_fun_ty getFunTyExpandingDicts_maybe t
+getFunTyExpandingDicts_maybe peek (FunTy arg result _) = Just (arg,result)
+getFunTyExpandingDicts_maybe peek
+       (AppTy (AppTy (TyConTy tycon _) arg) res) | isFunTyCon tycon = Just (arg, res)
+getFunTyExpandingDicts_maybe peek (SynTy _ _ t)            = getFunTyExpandingDicts_maybe peek t
+getFunTyExpandingDicts_maybe peek ty@(DictTy _ _ _) = getFunTyExpandingDicts_maybe peek (expandTy ty)
+
+getFunTyExpandingDicts_maybe True (ForAllTy _ ty)   = getFunTyExpandingDicts_maybe True ty
+       -- Ignore for-alls when peeking.  See note with defn of getFunTyExpandingDictsAndPeeking
+
+
+{-     This is a truly disgusting bit of code. 
+       It's used by the code generator to look at the rep of a newtype.
+       The code gen will have thrown away coercions involving that newtype, so
+       this is the other side of the coin.
+       Gruesome in the extreme.
+-}
+
+getFunTyExpandingDicts_maybe peek other
+  | not peek = Nothing -- that was easy
+  | otherwise
+  = case (maybeAppTyCon other) of
+      Just (tc, arg_tys)
+        | isNewTyCon tc && not (null data_cons)
+       -> getFunTyExpandingDicts_maybe peek inside_ty
+       where
+         data_cons   = tyConDataCons tc
+         [the_con]   = data_cons
+         [inside_ty] = dataConArgTys the_con arg_tys
+
+      other -> Nothing
+
+
+splitFunTy                        :: GenType t u -> ([GenType t u], GenType t u)
+splitFunTyExpandingDicts          :: Type        -> ([Type], Type)
+splitFunTyExpandingDictsAndPeeking :: Type       -> ([Type], Type)
+
+splitFunTy                        t = split_fun_ty getFunTy_maybe                       t
+splitFunTyExpandingDicts           t = split_fun_ty (getFunTyExpandingDicts_maybe False) t
+splitFunTyExpandingDictsAndPeeking t = split_fun_ty (getFunTyExpandingDicts_maybe True)  t
+       -- This "peeking" stuff is used only by the code generator.
+       -- It's interested in the representation type of things, ignoring:
+       --      newtype         Why???  Nuked SLPJ May 97.  We may not know the 
+       --                      rep of an abstractly imported newtype
+       --      foralls
+       --      expanding dictionary reps
+       --      synonyms, of course
 
 split_fun_ty get t = go t []
   where
@@ -262,8 +328,8 @@ mkTyConTy tycon
 
 applyTyCon :: TyCon -> [GenType t u] -> GenType t u
 applyTyCon tycon tys
-  = --ASSERT (not (isSynTyCon tycon))
-    (if (not (isSynTyCon tycon)) then \x->x else pprTrace "applyTyCon:" (pprTyCon PprDebug tycon)) $
+  = ASSERT (not (isSynTyCon tycon))
+    --(if (not (isSynTyCon tycon)) then \x->x else pprTrace "applyTyCon:" (pprTyCon PprDebug tycon)) $
     foldl AppTy (TyConTy tycon usageOmega) tys
 
 getTyCon_maybe              :: GenType t u -> Maybe TyCon
@@ -313,14 +379,15 @@ mkRhoTy theta ty =
 
 splitRhoTy :: GenType t u -> ([(Class,GenType t u)], GenType t u)
 splitRhoTy t =
-  go t []
+  go t t []
  where
-  go (FunTy (DictTy c t _) r _) ts = go r ((c,t):ts)
-  go (AppTy (AppTy (TyConTy tycon _) (DictTy c t _)) r) ts
+       -- See notes on type synonyms above
+  go syn_t (FunTy (DictTy c t _) r _) ts = go r r ((c,t):ts)
+  go syn_t (AppTy (AppTy (TyConTy tycon _) (DictTy c t _)) r) ts
        | isFunTyCon tycon
-       = go r ((c,t):ts)
-  go (SynTy _ _ t) ts = go t ts
-  go t ts = (reverse ts, t)
+       = go r r ((c,t):ts)
+  go syn_t (SynTy _ _ t) ts = go syn_t t ts
+  go syn_t t ts = (reverse ts, syn_t)
 
 
 mkTheta :: [Type] -> ThetaType
@@ -329,7 +396,11 @@ mkTheta dict_tys
   = map cvt dict_tys
   where
     cvt (DictTy clas ty _) = (clas, ty)
-    cvt other             = pprPanic "mkTheta:" (pprType PprDebug other)
+    cvt other             = panic "Type.mkTheta" -- pprPanic "mkTheta:" (pprType PprDebug other)
+
+isDictTy (DictTy _ _ _) = True
+isDictTy (SynTy  _ _ t) = isDictTy t
+isDictTy _             = False
 \end{code}
 
 
@@ -353,11 +424,12 @@ getForAllTyExpandingDicts_maybe ty@(DictTy _ _ _)  = getForAllTyExpandingDicts_m
 getForAllTyExpandingDicts_maybe _                 = Nothing
 
 splitForAllTy :: GenType t u-> ([t], GenType t u)
-splitForAllTy t = go t []
+splitForAllTy t = go t t []
               where
-                   go (ForAllTy tv t) tvs = go t (tv:tvs)
-                   go (SynTy _ _ t)   tvs = go t tvs
-                   go t               tvs = (reverse tvs, t)
+                       -- See notes on type synonyms above
+                   go syn_t (ForAllTy tv t) tvs = go t t (tv:tvs)
+                   go syn_t (SynTy _ _ t)   tvs = go syn_t t tvs
+                   go syn_t t               tvs = (reverse tvs, syn_t)
 \end{code}
 
 \begin{code}
@@ -383,7 +455,7 @@ maybeAppTyCon ty
        Nothing    -> Nothing
        Just tycon -> Just (tycon, arg_tys)
   where
-    (app_ty, arg_tys) = splitAppTy ty
+    (app_ty, arg_tys) = splitAppTys ty
 
 
 getAppTyCon
@@ -418,10 +490,10 @@ maybeAppSpecDataTyConExpandingDicts ty = maybe_app_data_tycon expandTy ty
 maybe_app_data_tycon expand ty
   = let
        expanded_ty       = expand ty
-       (app_ty, arg_tys) = splitAppTy expanded_ty
+       (app_ty, arg_tys) = splitAppTys expanded_ty
     in
     case (getTyCon_maybe app_ty) of
-       Just tycon |  --pprTrace "maybe_app:" (ppCat [ppr PprDebug (isDataTyCon tycon), ppr PprDebug (notArrowKind (typeKind expanded_ty))]) $
+       Just tycon |  --pprTrace "maybe_app:" (hsep [ppr PprDebug (isDataTyCon tycon), ppr PprDebug (notArrowKind (typeKind expanded_ty))]) $
                      isDataTyCon tycon && 
                      notArrowKind (typeKind expanded_ty)
                        -- Must be saturated for ty to be a data type
@@ -449,7 +521,7 @@ get_app_data_tycon maybe ty
   = case maybe ty of
       Just stuff -> stuff
 #ifdef DEBUG
-      Nothing    -> panic "Type.getAppDataTyCon" -- (pprGenType PprShowAll ty)
+      Nothing    -> panic "Type.getAppDataTyCon"--  (pprGenType PprShowAll ty)
 #endif
 
 
@@ -510,19 +582,35 @@ tyVarsOfType (ForAllUsageTy _ _ ty)       = tyVarsOfType ty
 
 tyVarsOfTypes :: [GenType (GenTyVar flexi) uvar] -> GenTyVarSet flexi
 tyVarsOfTypes tys = foldr (unionTyVarSets.tyVarsOfType) emptyTyVarSet tys
+
+-- Find the free names of a type, including the type constructors and classes it mentions
+namesOfType :: GenType (GenTyVar flexi) uvar -> NameSet
+namesOfType (TyVarTy tv)               = unitNameSet (getName tv)
+namesOfType (TyConTy tycon usage)      = unitNameSet (getName tycon)
+namesOfType (SynTy tycon tys ty)       = unitNameSet (getName tycon) `unionNameSets`
+                                         namesOfType ty
+namesOfType (FunTy arg res _)          = namesOfType arg `unionNameSets` namesOfType res
+namesOfType (AppTy fun arg)            = namesOfType fun `unionNameSets` namesOfType arg
+namesOfType (DictTy clas ty _)         = unitNameSet (getName clas) `unionNameSets`
+                                         namesOfType ty
+namesOfType (ForAllTy tyvar ty)                = namesOfType ty `minusNameSet` unitNameSet (getName tyvar)
+namesOfType (ForAllUsageTy _ _ ty)     = panic "forall usage"
 \end{code}
 
 
 Instantiating a type
 ~~~~~~~~~~~~~~~~~~~~
 \begin{code}
-applyTy :: GenType (GenTyVar flexi) uvar 
-       -> GenType (GenTyVar flexi) uvar 
-       -> GenType (GenTyVar flexi) uvar
+-- applyTy :: GenType (GenTyVar flexi) uvar 
+--     -> GenType (GenTyVar flexi) uvar 
+--     -> GenType (GenTyVar flexi) uvar
+
+applyTy :: Type -> Type -> Type
 
-applyTy (SynTy _ _ fun)  arg = applyTy fun arg
-applyTy (ForAllTy tv ty) arg = instantiateTy [(tv,arg)] ty
-applyTy other           arg = panic "applyTy"
+applyTy (SynTy _ _ fun)   arg = applyTy fun arg
+applyTy (ForAllTy tv ty)  arg = instantiateTy [(tv,arg)] ty
+applyTy ty@(DictTy _ _ _) arg = applyTy (expandTy ty) arg
+applyTy other            arg = panic "applyTy"
 \end{code}
 
 \begin{code}
@@ -561,6 +649,8 @@ instant_help ty lookup_tv deflt_tv choose_tycon
                                     else
                                        \x->x) ForAllTy (deflt_forall_tv tv) (go ty)
 
+instantiateTy [] ty = ty
+
 instantiateTy tenv ty
   = instant_help ty lookup_tv deflt_tv choose_tycon
                    if_usage if_forall bound_forall_tv_BAD deflt_forall_tv
@@ -593,20 +683,38 @@ instantiateTauTy tenv ty
     bound_forall_tv_BAD = panic "instantiateTauTy:bound_forall_tv"
     deflt_forall_tv tv  = panic "instantiateTauTy:deflt_forall_tv"
 
+
+-- applyTypeEnv applies a type environment to a type.
+-- It can handle shadowing; for example:
+--     f = /\ t1 t2 -> \ d ->
+--        letrec f' = /\ t1 -> \x -> ...(f' t1 x')...
+--         in f' t1
+-- Here, when we clone t1 to t1', say, we'll come across shadowing
+-- when applying the clone environment to the type of f'.
+--
+-- As a sanity check, we should also check that name capture 
+-- doesn't occur, but that means keeping track of the free variables of the
+-- range of the TyVarEnv, which I don't do just yet.
+--
+-- We don't use instant_help because we need to carry in the environment
+
 applyTypeEnvToTy tenv ty
-  = instant_help ty lookup_tv deflt_tv choose_tycon
-                   if_usage if_forall bound_forall_tv_BAD deflt_forall_tv
+  = go tenv ty
   where
-    lookup_tv = lookupTyVarEnv tenv
-    deflt_tv tv = TyVarTy tv
-    choose_tycon ty _ _ = ty
-    if_usage ty = ty
-    if_forall ty = ty
-    bound_forall_tv_BAD = False -- ToDo: probably should be True (i.e., no shadowing)
-    deflt_forall_tv tv  = case (lookup_tv tv) of
-                           Nothing -> tv
-                           Just (TyVarTy tv2) -> tv2
-                           _ -> panic "applyTypeEnvToTy"
+    go tenv ty@(TyVarTy tv)            = case (lookupTyVarEnv tenv tv) of
+                                            Nothing -> ty
+                                            Just ty -> ty
+    go tenv ty@(TyConTy tycon usage)   = ty
+    go tenv (SynTy tycon tys ty)       = SynTy tycon (map (go tenv) tys) (go tenv ty)
+    go tenv (FunTy arg res usage)      = FunTy (go tenv arg) (go tenv res) usage
+    go tenv (AppTy fun arg)            = AppTy (go tenv fun) (go tenv arg)
+    go tenv (DictTy clas ty usage)     = DictTy clas (go tenv ty) usage
+    go tenv (ForAllUsageTy uvar bds ty) = ForAllUsageTy uvar bds (go tenv ty)
+    go tenv (ForAllTy tv ty)           = ForAllTy tv (go tenv' ty)
+                                       where
+                                         tenv' = case lookupTyVarEnv tenv tv of
+                                                   Nothing -> tenv
+                                                   Just _  -> delFromTyVarEnv tenv tv
 \end{code}
 
 \begin{code}
@@ -616,15 +724,25 @@ instantiateUsage
 instantiateUsage = panic "instantiateUsage: not implemented"
 \end{code}
 
+
 At present there are no unboxed non-primitive types, so
 isUnboxedType is the same as isPrimType.
 
+We're a bit cavalier about finding out whether something is
+primitive/unboxed or not.  Rather than deal with the type
+arguemnts we just zoom into the function part of the type.
+That is, given (T a) we just recurse into the "T" part,
+ignoring "a".
+
 \begin{code}
-isPrimType, isUnboxedType :: GenType tyvar uvar -> Bool
+isPrimType, isUnboxedType :: Type -> Bool
 
 isPrimType (AppTy ty _)      = isPrimType ty
 isPrimType (SynTy _ _ ty)    = isPrimType ty
-isPrimType (TyConTy tycon _) = isPrimTyCon tycon
+isPrimType (TyConTy tycon _) = case maybeNewTyCon tycon of
+                                 Just (tyvars, ty) -> isPrimType ty
+                                 Nothing           -> isPrimTyCon tycon
+
 isPrimType _                = False
 
 isUnboxedType = isPrimType
@@ -632,16 +750,18 @@ isUnboxedType = isPrimType
 
 This is *not* right: it is a placeholder (ToDo 96/03 WDP):
 \begin{code}
-typePrimRep :: GenType tyvar uvar -> PrimRep
+typePrimRep :: Type -> PrimRep
 
 typePrimRep (SynTy _ _ ty)  = typePrimRep ty
 typePrimRep (AppTy ty _)    = typePrimRep ty
-typePrimRep (TyConTy tc _)  = if not (isPrimTyCon tc) then
-                                PtrRep
-                             else
-                                case (assocMaybe tc_primrep_list (uniqueOf tc)) of
+typePrimRep (TyConTy tc _)  
+  | isPrimTyCon tc         = case (assocMaybe tc_primrep_list (uniqueOf tc)) of
                                   Just xx -> xx
-                                  Nothing -> pprPanic "typePrimRep:" (pprTyCon PprDebug tc)
+                                  Nothing -> panic "Type.typePrimRep" -- pprPanic "typePrimRep:" (pprTyCon PprDebug tc)
+
+  | otherwise              = case maybeNewTyCon tc of
+                                 Just (tyvars, ty) | isPrimType ty -> typePrimRep ty
+                                 _ -> PtrRep   -- Default
 
 typePrimRep _              = PtrRep -- the "default"
 
@@ -659,7 +779,9 @@ tc_primrep_list
     ,(stablePtrPrimTyConKey,       StablePtrRep)
     ,(statePrimTyConKey,           VoidRep)
     ,(synchVarPrimTyConKey,        PtrRep)
-    ,(voidTyConKey,                VoidRep)
+    ,(voidTyConKey,                PtrRep)     -- Not VoidRep!  That's just for Void#
+                                               -- The type Void is represented by a pointer to
+                                               -- a bottom closure.
     ,(wordPrimTyConKey,                    WordRep)
     ]
 \end{code}
@@ -683,30 +805,36 @@ types.
 matchTy :: GenType t1 u1               -- Template
        -> GenType t2 u2                -- Proposed instance of template
        -> Maybe [(t1,GenType t2 u2)]   -- Matching substitution
+                                       
 
 matchTys :: [GenType t1 u1]            -- Templates
         -> [GenType t2 u2]             -- Proposed instance of template
-        -> Maybe [(t1,GenType t2 u2)]  -- Matching substitution
-
-matchTy  ty1  ty2  = match  [] [] ty1 ty2
-matchTys tys1 tys2 = match' [] (zipEqual "matchTys" tys1 tys2)
+        -> Maybe ([(t1,GenType t2 u2)],-- Matching substitution
+                  [GenType t2 u2])     -- Left over instance types
+
+matchTy  ty1  ty2  = match  ty1 ty2 (\s -> Just s) []
+matchTys tys1 tys2 = go [] tys1 tys2
+                  where
+                    go s []        tys2        = Just (s,tys2)
+                    go s (ty1:tys1) []         = trace "matchTys" Nothing
+                    go s (ty1:tys1) (ty2:tys2) = match ty1 ty2 (\s' -> go s' tys1 tys2) s
 \end{code}
 
 @match@ is the main function.
 
 \begin{code}
-match :: [(t1, GenType t2 u2)]                 -- r, the accumulating result
-      -> [(GenType t1 u1, GenType t2 u2)]      -- w, the work list
-      -> GenType t1 u1 -> GenType t2 u2                -- Current match pair
-      -> Maybe [(t1, GenType t2 u2)]
-
-match r w (TyVarTy v)         ty                   = match' ((v,ty) : r) w
-match r w (FunTy fun1 arg1 _)  (FunTy fun2 arg2 _)  = match r ((fun1,fun2):w) arg1 arg2
-match r w (AppTy fun1 arg1)  (AppTy fun2 arg2)      = match r ((fun1,fun2):w) arg1 arg2
-match r w (TyConTy con1 _)     (TyConTy con2 _)     | con1  == con2  = match' r w
-match r w (DictTy clas1 ty1 _) (DictTy clas2 ty2 _) | clas1 == clas2 = match r w ty1 ty2
-match r w (SynTy _ _ ty1)      ty2                 = match r w ty1 ty2
-match r w ty1                 (SynTy _ _ ty2)      = match r w ty1 ty2
+match :: GenType t1 u1 -> GenType t2 u2                        -- Current match pair
+      -> ([(t1, GenType t2 u2)] -> Maybe result)       -- Continuation
+      -> [(t1, GenType t2 u2)]                         -- Current substitution
+      -> Maybe result
+
+match (TyVarTy v)         ty                   k = \s -> k ((v,ty) : s)
+match (FunTy fun1 arg1 _)  (FunTy fun2 arg2 _)  k = match fun1 fun2 (match arg1 arg2 k)
+match (AppTy fun1 arg1)    (AppTy fun2 arg2)    k = match fun1 fun2 (match arg1 arg2 k)
+match (TyConTy con1 _)     (TyConTy con2 _)     k | con1  == con2  = k
+match (DictTy clas1 ty1 _) (DictTy clas2 ty2 _) k | clas1 == clas2 = match ty1 ty2 k
+match (SynTy _ _ ty1)      ty2                 k = match ty1 ty2 k
+match ty1                     (SynTy _ _ ty2)  k = match ty1 ty2 k
 
        -- With type synonyms, we have to be careful for the exact
        -- same reasons as in the unifier.  Please see the
@@ -714,10 +842,7 @@ match r w ty1                     (SynTy _ _ ty2)      = match r w ty1 ty2
        -- here! (WDP 95/05)
 
 -- Catch-all fails
-match _ _ _ _ = Nothing
-
-match' r []           = Just r
-match' r ((ty1,ty2):w) = match r w ty1 ty2
+match _ _ _ = \s -> Nothing
 \end{code}
 
 %************************************************************************
@@ -843,3 +968,53 @@ eqTy t1 t2 =
   eqBounds uve (u1:b1) (u2:b2) = eqUVar uve u1 u2 && eqBounds uve b1 b2
   eqBounds uve _ _ = False
 \end{code}
+
+\begin{code}
+showTypeCategory :: Type -> Char
+  {-
+       {C,I,F,D}   char, int, float, double
+       T           tuple
+       S           other single-constructor type
+       {c,i,f,d}   unboxed ditto
+       t           *unpacked* tuple
+       s           *unpacked" single-cons...
+
+       v           void#
+       a           primitive array
+
+       E           enumeration type
+       +           dictionary, unless it's a ...
+       L           List
+       >           function
+       M           other (multi-constructor) data-con type
+       .           other type
+       -           reserved for others to mark as "uninteresting"
+    -}
+showTypeCategory ty
+  = if isDictTy ty
+    then '+'
+    else
+      case getTyCon_maybe ty of
+       Nothing -> if maybeToBool (getFunTy_maybe ty)
+                  then '>'
+                  else '.'
+
+       Just tycon ->
+          let utc = uniqueOf tycon in
+         if      utc == charDataConKey    then 'C'
+         else if utc == intDataConKey     then 'I'
+         else if utc == floatDataConKey   then 'F'
+         else if utc == doubleDataConKey  then 'D'
+         else if utc == integerDataConKey then 'J'
+         else if utc == charPrimTyConKey  then 'c'
+         else if (utc == intPrimTyConKey || utc == wordPrimTyConKey
+               || utc == addrPrimTyConKey)                then 'i'
+         else if utc  == floatPrimTyConKey                then 'f'
+         else if utc  == doublePrimTyConKey               then 'd'
+         else if isPrimTyCon tycon {- array, we hope -}   then 'A'
+         else if isEnumerationTyCon tycon                 then 'E'
+         else if isTupleTyCon tycon                       then 'T'
+         else if maybeToBool (maybeTyConSingleCon tycon)  then 'S'
+         else if utc == listTyConKey                      then 'L'
+         else 'M' -- oh, well...
+\end{code}