2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
4 \section[TyCon]{Type constructors}
7 #include "HsVersions.h"
10 TyCon(..), -- not abstract; usually grabbed via AbsUniType
11 Arity(..), -- synonym for Int
12 mkSynonymTyCon, mkDataTyCon, mkTupleTyCon,
13 mkPrimTyCon, mkSpecTyCon,
19 getPodizedPodDimension,
20 #endif {- Data Parallel Haskell -}
22 isSynTyCon, isVisibleSynTyCon, isDataTyCon,
23 isPrimTyCon, isBoxedTyCon,
24 maybeCharLikeTyCon, maybeIntLikeTyCon,
25 maybeFloatLikeTyCon, maybeDoubleLikeTyCon,
26 isEnumerationTyCon, --UNUSED: isEnumerationTyConMostly,
28 isLocalSpecTyCon, isLocalGenTyCon, isBigTupleTyCon,
29 maybeSingleConstructorTyCon,
30 derivedFor, --UNUSED: preludeClassDerivedFor,
33 getTyConArity, getTyConDataCons,
34 getTyConTyVarTemplates,
39 -- to make the interface self-sufficient...
40 Class, Id, FullName, PrimKind, TyVarTemplate, UniType,
41 Unique, Maybe, DataCon(..)
44 IMPORT_Trace -- ToDo: rm (debugging)
46 import AbsPrel ( charPrimTy, intPrimTy, floatPrimTy,
47 doublePrimTy, pRELUDE_BUILTIN
50 import Class ( getClassKey, Class
51 IF_ATTACK_PRAGMAS(COMMA cmpClass)
53 import Id -- DPH wants to export various things as well
55 import Maybes ( Maybe(..) )
56 import NameTypes -- various types to do with names
57 import Outputable -- class for printing, forcing
58 import Pretty -- pretty-printing utilities
59 import PrimKind ( PrimKind(..) )
61 import TyVar ( TyVarTemplate, alphaTyVars )
62 import Unique ( cmpUnique, Unique )
63 import UniTyFuns ( getTauType, getUniDataTyCon, pprTyCon,
64 cmpUniTypeMaybeList, specMaybeTysSuffix
65 IF_ATTACK_PRAGMAS(COMMA pprUniType COMMA splitType)
67 import UniType ( UniType
68 IF_ATTACK_PRAGMAS(COMMA cmpUniType)
73 %************************************************************************
75 \subsection[TyCon-basics]{@TyCon@ type and basic operations}
77 %************************************************************************
81 = SynonymTyCon Unique{-TyConKey-} -- for fast comparison
84 [TyVarTemplate]-- Argument type variables
85 UniType -- Right-hand side, mentioning these type vars
86 -- Acts as a template for the expansion when
87 -- the tycon is applied to some types.
88 Bool -- True <=> expansion is visible to user;
89 -- i.e., *not* abstract
91 | DataTyCon Unique{-TyConKey-}
94 [TyVarTemplate] -- see note below
95 [Id] -- its data constructors
96 [Class] -- classes which have derived instances
97 Bool -- True <=> data constructors are visible
98 -- to user; i.e., *not* abstract
100 | TupleTyCon Arity -- just a special case of DataTyCon
102 | PrimTyCon -- Primitive types; cannot be defined in Haskell
103 -- Always unboxed; hence never represented by a closure
104 -- Often represented by a bit-pattern for the thing
105 -- itself (eg Int#), but sometimes by a pointer to
106 -- a heap-allocated object (eg ArrInt#).
107 -- The primitive types Arr# and StablePtr# have
108 -- parameters (hence arity /= 0); but the rest don't.
111 Arity -- Arity is *usually* 0.
112 ([PrimKind] -> PrimKind)
113 -- Only arrays use the list in a non-trivial way.
114 -- Length of that list must == arity.
116 -- Used only for naming purposes in CLabels
117 | SpecTyCon TyCon -- original data (or tuple) tycon
118 [Maybe UniType] -- specialising types
121 | ProcessorTyCon Arity -- special cased in same way as tuples
123 | PodizedPodTyCon Int -- podized dimension
124 TyCon -- Thing the pod contains
130 {\em Note about the the @[TyVarTemplates]@ in @DataTyCon@ (and
131 @SynonymTyCon@, too? ToDo):} they should be the type variables which
132 appeared in the original @data@ declaration. They are there {\em for
133 documentation purposes only}. In particular, when printing out
134 interface files, we want to use the same type-variable names as
135 appeared in the @data@ declaration for that type constructor.
136 However, they have no semantic significance.
138 We could also ensure that the data constructors in the @[Id]@ had the
139 {\em same} type vars in their @[TyVarTemplate]@ lists, so that we
140 don't have to do a translation on printout.
143 Constructor functions, and simple access functions:
145 mkSynonymTyCon = SynonymTyCon
146 mkDataTyCon = DataTyCon
147 mkTupleTyCon = TupleTyCon
148 mkPrimTyCon = PrimTyCon
149 mkSpecTyCon = SpecTyCon
152 mkProcessorTyCon= ProcessorTyCon
153 mkPodizedPodTyCon = PodizedPodTyCon
154 #endif {- Data Parallell Haskell -}
157 %************************************************************************
159 \subsection[TyCon-extractors]{Extractors for @TyCon@}
161 %************************************************************************
164 getTyConArity (PrimTyCon _ _ a _) = a
165 getTyConArity (SynonymTyCon _ _ a _ _ _) = a
166 getTyConArity (DataTyCon _ _ a _ _ _ _) = a
167 getTyConArity (SpecTyCon tc tys) = getTyConArity tc - length tys
168 getTyConArity (TupleTyCon a) = a
170 getTyConArity (ProcessorTyCon a) = a
171 getTyConArity (PodizedPodTyCon _ _) = panic "getTyConArity: pod"
172 #endif {- Data Parallel Haskell -}
174 getTyConKind (PrimTyCon _ _ _ kind_fn) kinds = kind_fn kinds
176 getTyConKind (PodizedPodTyCon _ tc) kinds = getTyConKind tc kinds
177 #endif {- Data Parallel Haskell -}
178 getTyConKind other kinds = PtrKind -- the "default"
180 getTyConDerivings (DataTyCon _ _ _ _ _ derivings _) = derivings
181 getTyConDerivings (SpecTyCon tc tys) = panic "getTyConDerivings:SpecTyCon"
183 getTyConDerivings (PodizedPodTyCon _ _) = panic "getTyConDerivings:pod"
184 #endif {- Data Parallel Haskell -}
185 getTyConDerivings other = []
186 -- NB: we do *not* report the PreludeCore types "derivings"...
188 getTyConDataCons (DataTyCon _ _ _ _ data_cons _ _) = data_cons
189 getTyConDataCons (SpecTyCon tc tys) = panic "getTyConDataCons:SpecTyCon"
190 getTyConDataCons (TupleTyCon a) = [mkTupleCon a]
192 getTyConDataCons (ProcessorTyCon a) = [mkProcessorCon a]
193 getTyConDataCons (PodizedPodTyCon _ _) = panic "getTyConDataCons: pod"
194 #endif {- Data Parallel Haskell -}
195 getTyConDataCons other_tycon = []
197 For the use of @getTyConDataCons@ in @MkUnfoldings@, the behaviour
198 above is right: return @[]@ if not an algebraic data type. I am not
199 certain if that's right for all uses (perhaps should @panic@?) [WDP]
201 The following function returns (free) type-variables associated with a
202 given @TyCon@. As the information about these variables is distributed
203 over the @TyCon@'s constructors we take them from the type of any
204 of the constructors assuming that the variables in the remaining
205 type constructors are the same (responsible for keeping this assumption
206 valid is the typechecker). ToDo: rm this old comment?
208 getTyConTyVarTemplates (SynonymTyCon _ _ _ tvs _ _) = tvs
209 getTyConTyVarTemplates (DataTyCon _ _ _ tvs _ _ _) = tvs
210 getTyConTyVarTemplates (SpecTyCon tc tys) = panic "getTyConTyVarTemplates:SpecTyCon"
211 getTyConTyVarTemplates (TupleTyCon a) = take a alphaTyVars
212 getTyConTyVarTemplates (PrimTyCon _ _ _ _) = [] -- ToDo: ???
214 getTyConTyVarTemplates (ProcessorTyCon a) = take a alphaTyVars
215 getTyConTyVarTemplates (PodizedPodTyCon _ _) = panic "getTyConTyVarTem"
216 #endif {- Data Parallel Haskell -}
220 getTyConFamilySize :: TyCon -> Maybe Int -- return Nothing if we don't know
222 getTyConFamilySize (TupleTyCon _) = Just 1
223 getTyConFamilySize (SpecTyCon tc tys) = getTyConFamilySize tc
224 getTyConFamilySize (DataTyCon _ _ _ _ dcs _ _)
226 no_data_cons = length dcs
228 if no_data_cons == 0 then Nothing else Just no_data_cons
231 -- ToDo: if 0 then the answer is really "I don't know"; what then?
232 getTyConFamilySize tc@(PrimTyCon _ _ _ _)
233 = pprPanic "getTyConFamilySize:prim:" (ppr PprDebug tc)
234 getTyConFamilySize (SynonymTyCon _ _ _ _ expand _)
235 = pprTrace "getTyConFamilySize:Syn:" (ppr PprDebug expand) (
237 (tycon,_,data_cons) = getUniDataTyCon (getTauType expand)
238 no_data_cons = length data_cons
240 if no_data_cons == 0 then Nothing else Just no_data_cons
244 getTyConFamilySize (ProcessorTyCon _) = Just 1
245 getTyConFamilySize (PodizedPodTyCon _ _) = panic "getTyConFamilySize: Pod"
246 #endif {- Data Parallel Haskell -}
249 %************************************************************************
251 \subsection[TyCon-predicates]{Predicates on @TyCon@s}
253 %************************************************************************
256 -- True <=> Algebraic data type
257 isDataTyCon (DataTyCon _ _ _ _ _ _ _) = True
258 isDataTyCon (SpecTyCon tc tys) = isDataTyCon tc
259 isDataTyCon (TupleTyCon _) = True
261 isDataTyCon (ProcessorTyCon _) = True
262 isDataTyCon (PodizedPodTyCon _ tc) = isDataTyCon tc
263 #endif {- Data Parallel Haskell -}
264 isDataTyCon other = False
267 isSynTyCon (SynonymTyCon _ _ _ _ _ _) = True
268 isSynTyCon (SpecTyCon tc tys) = panic "isSynTyCon: SpecTyCon"
270 isSynTyCon (PodizedPodTyCon _ _) = panic "isSynTyCon: Pod"
271 #endif {- Data Parallel Haskell -}
272 isSynTyCon other = False
274 isVisibleSynTyCon (SynonymTyCon _ _ _ _ _ visible) = visible
275 isVisibleSynTyCon other_tycon = panic "isVisibleSynTyCon"
277 isPrimTyCon (PrimTyCon _ _ _ _) = True
278 isPrimTyCon (SpecTyCon tc tys) = isPrimTyCon tc
280 isPrimTyCon (PodizedPodTyCon _ tc) = isPrimTyCon tc
281 #endif {- Data Parallel Haskell -}
282 isPrimTyCon other = False
284 -- At present there are no unboxed non-primitive types, so isBoxedTyCon is
285 -- just the negation of isPrimTyCon.
286 isBoxedTyCon (PrimTyCon _ _ _ _) = False
287 isBoxedTyCon (SpecTyCon tc tys) = isBoxedTyCon tc
289 isBoxedTyCon (PodizedPodTyCon _ tc) = isBoxedTyCon tc
290 #endif {- Data Parallel Haskell -}
291 isBoxedTyCon other = True
295 The @maybeCharLikeTyCon@ predicate tests for a tycon with no type
296 variables, and one constructor which has one argument of type
297 @CharPrim@. Similarly @maybeIntLikeTyCon@, etc.
299 ToDo:SpecTyCon Do we want to CharLike etc for SpecTyCons ???
302 maybeCharLikeTyCon (DataTyCon _ _ _ [] [con] [] _) = maybe_foo_like con charPrimTy
304 maybeCharLikeTyCon (PodizedPodTyCon _ _) = panic "maybeCharLikeTyCon: Pod"
305 #endif {- Data Parallel Haskell -}
306 maybeCharLikeTyCon other = Nothing
308 maybeIntLikeTyCon (DataTyCon _ _ _ [] [con] [] _) = maybe_foo_like con intPrimTy
310 maybeIntLikeTyCon (PodizedPodTyCon _ _) = panic "maybeIntLikeTyCon: Pod"
311 #endif {- Data Parallel Haskell -}
312 maybeIntLikeTyCon other = Nothing
314 maybeFloatLikeTyCon (DataTyCon _ _ _ [] [con] [] _) = maybe_foo_like con floatPrimTy
316 maybeFloatLikeTyCon (PodizedPodTyCon _ _) = panic "maybeFloatLikeTyCon: Pod"
317 #endif {- Data Parallel Haskell -}
318 maybeFloatLikeTyCon other = Nothing
320 maybeDoubleLikeTyCon (DataTyCon _ _ _ [] [con] [] _) = maybe_foo_like con doublePrimTy
322 maybeDoubleLikeTyCon (PodizedPodTyCon _ _) = panic "maybeDoubleLikeTyCon: Pod"
323 #endif {- Data Parallel Haskell -}
324 maybeDoubleLikeTyCon other = Nothing
326 maybe_foo_like con prim_type_to_match
327 = case (getDataConSig con) of
328 ([], [], [should_be_prim], _)
329 | should_be_prim == prim_type_to_match -> Just con
333 isProcessorTyCon :: TyCon -> Bool
334 isProcessorTyCon (ProcessorTyCon _) = True
335 isProcessorTyCon other = False
337 isPodizedPodTyCon :: TyCon -> Bool
338 isPodizedPodTyCon (PodizedPodTyCon _ _) = True
339 isPodizedPodTyCon other = False
341 getPodizedPodDimension::TyCon -> Int
342 getPodizedPodDimension (PodizedPodTyCon d _) = d
343 #endif {- Data Parallel Haskell -}
347 isEnumerationTyCon :: TyCon -> Bool
349 isEnumerationTyCon (TupleTyCon arity)
351 isEnumerationTyCon (DataTyCon _ _ _ _ data_cons _ _)
352 = not (null data_cons) && all is_nullary data_cons
354 is_nullary con = case (getDataConSig con) of { (_,_, arg_tys, _) ->
357 -- isEnumerationTyCon (SpecTyCon tc tys) -- ToDo:SpecTyCon
358 isEnumerationTyCon other = pprPanic "isEnumerationTyCon: " (ppr PprShowAll other)
361 -- this one is more of a *heuristic*
363 isEnumerationTyConMostly :: TyCon -> Bool
365 isEnumerationTyConMostly (TupleTyCon arity) = arity == 0
367 isEnumerationTyConMostly tycon@(DataTyCon _ _ _ _ data_cons _ _)
368 = isEnumerationTyCon tycon
369 || four_or_more data_cons 0
371 four_or_more :: [Id] -> Int -> Bool
373 four_or_more [] acc = if acc >= 4 then True else False
374 four_or_more (c:cs) acc
375 = case (getDataConSig c) of { (_,_, arg_tys, _) ->
376 four_or_more cs (if (null arg_tys) then acc+1 else acc)
378 -- isEnumerationTyConMostly (SpecTyCon tc tys) -- ToDo:SpecTyCon
382 maybeSingleConstructorTyCon :: TyCon -> Maybe Id
383 maybeSingleConstructorTyCon (TupleTyCon arity) = Just (mkTupleCon arity)
384 maybeSingleConstructorTyCon (DataTyCon _ _ _ _ [c] _ _) = Just c
385 maybeSingleConstructorTyCon (DataTyCon _ _ _ _ _ _ _) = Nothing
386 maybeSingleConstructorTyCon (PrimTyCon _ _ _ _) = Nothing
387 maybeSingleConstructorTyCon (SpecTyCon tc tys) = panic "maybeSingleConstructorTyCon:SpecTyCon"
388 -- requires DataCons of TyCon
391 @derivedFor@ reports if we have an {\em obviously}-derived instance
392 for the given class/tycon. Of course, you might be deriving something
393 because it a superclass of some other obviously-derived class---this
394 function doesn't deal with that.
396 ToDo:SpecTyCon Do we want derivedFor etc for SpecTyCons ???
399 derivedFor :: Class -> TyCon -> Bool
401 clas `derivedFor` (DataTyCon _ _ _ _ _ derivs _) = clas `is_elem` derivs
402 clas `derivedFor` something_weird = False
404 x `is_elem` y = isIn "X_derivedFor" x y
407 preludeClassDerivedFor :: Unique{-ClassKey-} -> TyCon -> Bool
409 preludeClassDerivedFor key (DataTyCon _ _ _ _ _ derivs _)
410 = key `is_elem` (map getClassKey derivs)
411 preludeClassDerivedFor key something_weird = False
416 isTupleTyCon (TupleTyCon arity) = arity >= 2 -- treat "0-tuple" specially
417 isTupleTyCon (SpecTyCon tc tys) = isTupleTyCon tc
418 isTupleTyCon other = False
421 @isLocalSpecTyCon@ determines if a tycon has specialisations created
422 locally: locally defined tycons and any tycons from the prelude.
423 But *not* if we're compiling the prelude itself...
425 @isLocalGenTyCon@ determines if constructor code for a tycon is
426 generated locally: locally defined tycons and big tuple tycons.
429 isLocalSpecTyCon :: Bool -> TyCon -> Bool
431 isLocalSpecTyCon compiling_prelude tc
432 = isLocallyDefined tc || (fromPreludeCore tc && not compiling_prelude)
434 isLocalGenTyCon (SpecTyCon tc tys) = isLocalGenTyCon tc
435 isLocalGenTyCon tc = isBigTupleTyCon tc || isLocallyDefined tc
437 isBigTupleTyCon (TupleTyCon arity) = arity > 32
438 -- Tuple0 to Tuple32 declared in prelude
439 -- HEY! Nice magic constant! WDP 95/06
440 isBigTupleTyCon (SpecTyCon tc _) = isBigTupleTyCon tc
441 isBigTupleTyCon _ = False
444 %************************************************************************
446 \subsection[TyCon-instances]{Instance declarations for @TyCon@}
448 %************************************************************************
450 @TyCon@s are compared by comparing their @Unique@s.
452 The strictness analyser needs @Ord@. It is a lexicographic order with
453 the property @(a<=b) || (b<=a)@.
456 cmpTyCon (SynonymTyCon k1 _ _ _ _ _) (SynonymTyCon k2 _ _ _ _ _)= cmpUnique k1 k2
457 cmpTyCon (DataTyCon k1 _ _ _ _ _ _) (DataTyCon k2 _ _ _ _ _ _) = cmpUnique k1 k2
458 cmpTyCon (TupleTyCon a1) (TupleTyCon a2) = cmp_i a1 a2
459 cmpTyCon (PrimTyCon k1 _ _ _) (PrimTyCon k2 _ _ _) = cmpUnique k1 k2
460 cmpTyCon (SpecTyCon tc1 mtys1) (SpecTyCon tc2 mtys2)
461 = case cmpTyCon tc1 tc2 of { EQ_ -> cmpUniTypeMaybeList mtys1 mtys2; other -> other }
463 cmpTyCon (ProcessorTyCon a1) (ProcessorTyCon a2) = cmp_i a1 a2
464 cmpTyCon (PodizedPodTyCon d1 tc1) (PodizedPodTyCon d2 tc2)
465 = case cmp_i d1 d2 of { EQ_ -> cmpTyCon tc1 tc2; other -> other }
466 #endif {- Data Parallel Haskell -}
468 -- now we *know* the tags are different, so...
469 cmpTyCon other_1 other_2
471 tag1 = tag_TyCon other_1
472 tag2 = tag_TyCon other_2
474 if tag1 _LT_ tag2 then LT_ else GT_
476 tag_TyCon (SynonymTyCon _ _ _ _ _ _) = (ILIT(1) :: FAST_INT)
477 tag_TyCon (DataTyCon _ _ _ _ _ _ _)= ILIT(2)
478 tag_TyCon (TupleTyCon _) = ILIT(3)
479 tag_TyCon (PrimTyCon _ _ _ _) = ILIT(4)
480 tag_TyCon (SpecTyCon _ _) = ILIT(5)
482 tag_TyCon (ProcessorTyCon _) = ILIT(6)
483 tag_TyCon (PodizedPodTyCon _ _) = ILIT(7)
484 #endif {- Data Parallel Haskell -}
486 cmp_i :: Int -> Int -> TAG_
488 = if a1 == a2 then EQ_ else if a1 < a2 then LT_ else GT_
492 eqTyCon :: TyCon -> TyCon -> Bool
494 eqTyCon a b = case cmpTyCon a b of { EQ_ -> True; _ -> False }
496 instance Eq TyCon where
497 a == b = case cmpTyCon a b of { EQ_ -> True; _ -> False }
498 a /= b = case cmpTyCon a b of { EQ_ -> False; _ -> True }
500 instance Ord TyCon where
501 a <= b = case cmpTyCon a b of { LT_ -> True; EQ_ -> True; GT__ -> False }
502 a < b = case cmpTyCon a b of { LT_ -> True; EQ_ -> False; GT__ -> False }
503 a >= b = case cmpTyCon a b of { LT_ -> False; EQ_ -> True; GT__ -> True }
504 a > b = case cmpTyCon a b of { LT_ -> False; EQ_ -> False; GT__ -> True }
505 #ifdef __GLASGOW_HASKELL__
506 _tagCmp a b = case cmpTyCon a b of { LT_ -> _LT; EQ_ -> _EQ; GT__ -> _GT }
511 instance NamedThing TyCon where
512 getExportFlag (TupleTyCon _) = NotExported
514 getExportFlag (ProcessorTyCon _) = NotExported
515 getExportFlag (PodizedPodTyCon _ tc) = getExportFlag tc
516 #endif {- Data Parallel Haskell -}
517 getExportFlag other = getExportFlag (get_name other)
519 isLocallyDefined (TupleTyCon _) = False
521 isLocallyDefined (ProcessorTyCon _) = False
522 isLocallyDefined (PodizedPodTyCon _ tc) = isLocallyDefined tc
523 #endif {- Data Parallel Haskell -}
524 isLocallyDefined other = isLocallyDefined (get_name other)
526 getOrigName (TupleTyCon a) = (pRELUDE_BUILTIN, _PK_ ("Tuple" ++ (show a)))
527 getOrigName (SpecTyCon tc tys) = let (m,n) = getOrigName tc in
528 (m, n _APPEND_ specMaybeTysSuffix tys)
530 getOrigName (ProcessorTyCon a) = ("PreludeBuiltin", "Processor" ++ (show a))
531 getOrigName (PodizedPodTyCon d tc) = let (m,n) = getOrigName tc in
533 #endif {- Data Parallel Haskell -}
534 getOrigName other = getOrigName (get_name other)
536 getOccurrenceName (TupleTyCon a) = _PK_ ("Tuple" ++ (show a))
537 getOccurrenceName (SpecTyCon tc tys) = getOccurrenceName tc _APPEND_ specMaybeTysSuffix tys
539 getOccurrenceName (ProcessorTyCon a) = "Processor" ++ (show a)
540 getOccurrenceName (PodizedPodTyCon d tc) = getOccurrenceName tc ++
542 #endif {- Data Parallel Haskell -}
543 getOccurrenceName other = getOccurrenceName (get_name other)
545 getInformingModules (TupleTyCon a) = panic "getInformingModule:TupleTyCon"
547 getInformingModules (ProcessorTyCon a) = "Processor" ++ (show a)
548 getInformingModules (PodizedPodTyCon d tc) = getInformingModule tc ++
550 #endif {- Data Parallel Haskell -}
551 getInformingModules other = getInformingModules (get_name other)
553 getSrcLoc (TupleTyCon _) = mkBuiltinSrcLoc
555 getSrcLoc (ProcessorTyCon _) = mkBuiltinSrcLoc
556 getSrcLoc (PodizedPodTyCon _ tc) = getSrcLoc tc
557 #endif {- Data Parallel Haskell -}
558 getSrcLoc other = getSrcLoc (get_name other)
560 getTheUnique other = panic "NamedThing.TyCon.getTheUnique"
562 fromPreludeCore (TupleTyCon a) = True
564 fromPreludeCore (ProcessorTyCon a) = True
565 fromPreludeCore (PodizedPodTyCon _ tc) = fromPreludeCore tc
566 #endif {- Data Parallel Haskell -}
567 fromPreludeCore other = fromPreludeCore (get_name other)
569 hasType = panic "NamedThing.TyCon.hasType"
570 getType = panic "NamedThing.TyCon.getType"
573 Emphatically un-exported:
575 get_name (SynonymTyCon _ n _ _ _ _) = n
576 get_name (DataTyCon _ n _ _ _ _ _) = n
577 get_name (PrimTyCon _ n _ _) = n
578 get_name (SpecTyCon tc _) = get_name tc
581 And the usual output stuff:
583 instance Outputable TyCon where
584 ppr sty tycon = pprTyCon sty tycon [{-No Specialisations-}]