(F)SLIT -> (f)sLit in TysWiredIn
[ghc-hetmet.git] / compiler / prelude / TysWiredIn.lhs
1 %
2 % (c) The GRASP Project, Glasgow University, 1994-1998
3 %
4 \section[TysWiredIn]{Wired-in knowledge about {\em non-primitive} types}
5
6 This module is about types that can be defined in Haskell, but which
7 must be wired into the compiler nonetheless.
8
9 This module tracks the ``state interface'' document, ``GHC prelude:
10 types and operations.''
11
12 \begin{code}
13 {-# OPTIONS -w #-}
14 -- The above warning supression flag is a temporary kludge.
15 -- While working on this module you are encouraged to remove it and fix
16 -- any warnings in the module. See
17 --     http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
18 -- for details
19
20 module TysWiredIn (
21         wiredInTyCons, 
22
23         boolTy, boolTyCon, boolTyCon_RDR, boolTyConName,
24         trueDataCon,  trueDataConId,  true_RDR,
25         falseDataCon, falseDataConId, false_RDR,
26
27         charTyCon, charDataCon, charTyCon_RDR,
28         charTy, stringTy, charTyConName,
29
30         
31         doubleTyCon, doubleDataCon, doubleTy, doubleTyConName, 
32         
33         floatTyCon, floatDataCon, floatTy, floatTyConName,
34
35         intTyCon, intDataCon, intTyCon_RDR, intDataCon_RDR, intTyConName,
36         intTy,
37
38         listTyCon, nilDataCon, consDataCon,
39         listTyCon_RDR, consDataCon_RDR, listTyConName,
40         mkListTy,
41
42         -- tuples
43         mkTupleTy,
44         tupleTyCon, tupleCon, 
45         unitTyCon, unitDataCon, unitDataConId, pairTyCon, 
46         unboxedSingletonTyCon, unboxedSingletonDataCon,
47         unboxedPairTyCon, unboxedPairDataCon,
48        
49         boxedTupleArr, unboxedTupleArr,
50
51         unitTy,
52
53         -- parallel arrays
54         mkPArrTy,
55         parrTyCon, parrFakeCon, isPArrTyCon, isPArrFakeCon,
56         parrTyCon_RDR, parrTyConName
57     ) where
58
59 import {-# SOURCE #-} MkId( mkDataConIds )
60
61 -- friends:
62 import PrelNames
63 import TysPrim
64
65 -- others:
66 import Constants        ( mAX_TUPLE_SIZE )
67 import Module           ( Module )
68 import RdrName          ( nameRdrName )
69 import Name             ( Name, BuiltInSyntax(..), nameUnique, nameOccName, 
70                           nameModule, mkWiredInName )
71 import OccName          ( mkOccNameFS, tcName, dataName, mkTupleOcc,
72                           mkDataConWorkerOcc )
73 import DataCon          ( DataCon, mkDataCon, dataConWorkId, dataConSourceArity )
74 import Var              ( TyVar, tyVarKind )
75 import TyCon            ( TyCon, AlgTyConRhs(DataTyCon), tyConDataCons,
76                           mkTupleTyCon, mkAlgTyCon, tyConName,
77                           TyConParent(NoParentTyCon) )
78
79 import BasicTypes       ( Arity, RecFlag(..), Boxity(..), isBoxed,
80                           StrictnessMark(..) )
81
82 import Type             ( Type, mkTyConTy, mkTyConApp, mkTyVarTy, mkTyVarTys,
83                           TyThing(..) )
84 import Coercion         ( unsafeCoercionTyCon, symCoercionTyCon,
85                           transCoercionTyCon, leftCoercionTyCon, 
86                           rightCoercionTyCon, instCoercionTyCon )
87 import TypeRep          ( mkArrowKinds, liftedTypeKind, ubxTupleKind )
88 import Unique           ( incrUnique, mkTupleTyConUnique,
89                           mkTupleDataConUnique, mkPArrDataConUnique )
90 import Array
91 import FastString
92 import Outputable
93
94 alpha_tyvar = [alphaTyVar]
95 alpha_ty    = [alphaTy]
96 \end{code}
97
98
99 %************************************************************************
100 %*                                                                      *
101 \subsection{Wired in type constructors}
102 %*                                                                      *
103 %************************************************************************
104
105 If you change which things are wired in, make sure you change their
106 names in PrelNames, so they use wTcQual, wDataQual, etc
107
108 \begin{code}
109 wiredInTyCons :: [TyCon]        -- Excludes tuples
110 -- This list is used only to define PrelInfo.wiredInThings
111
112 -- It does not need to include kind constructors, because
113 -- all that wiredInThings does is to initialise the Name table,
114 -- and kind constructors don't appear in source code.
115
116 wiredInTyCons = [ unitTyCon     -- Not treated like other tuples, because
117                                 -- it's defined in GHC.Base, and there's only
118                                 -- one of it.  We put it in wiredInTyCons so
119                                 -- that it'll pre-populate the name cache, so
120                                 -- the special case in lookupOrigNameCache 
121                                 -- doesn't need to look out for it
122               , boolTyCon
123               , charTyCon
124               , doubleTyCon
125               , floatTyCon
126               , intTyCon
127               , listTyCon
128               , parrTyCon
129               , unsafeCoercionTyCon
130               , symCoercionTyCon
131               , transCoercionTyCon
132               , leftCoercionTyCon
133               , rightCoercionTyCon
134               , instCoercionTyCon
135               ]
136 \end{code}
137
138 \begin{code}
139 mkWiredInTyConName :: BuiltInSyntax -> Module -> FastString -> Unique -> TyCon -> Name
140 mkWiredInTyConName built_in mod fs uniq tycon
141   = mkWiredInName mod (mkOccNameFS tcName fs) uniq
142                   (ATyCon tycon)        -- Relevant TyCon
143                   built_in
144
145 mkWiredInDataConName :: BuiltInSyntax -> Module -> FastString -> Unique -> DataCon -> Name
146 mkWiredInDataConName built_in mod fs uniq datacon
147   = mkWiredInName mod (mkOccNameFS dataName fs) uniq
148                   (ADataCon datacon)    -- Relevant DataCon
149                   built_in
150
151 charTyConName     = mkWiredInTyConName   UserSyntax gHC_BASE (fsLit "Char") charTyConKey charTyCon
152 charDataConName   = mkWiredInDataConName UserSyntax gHC_BASE (fsLit "C#") charDataConKey charDataCon
153 intTyConName      = mkWiredInTyConName   UserSyntax gHC_BASE (fsLit "Int") intTyConKey   intTyCon
154 intDataConName    = mkWiredInDataConName UserSyntax gHC_BASE (fsLit "I#") intDataConKey  intDataCon
155                                                   
156 boolTyConName     = mkWiredInTyConName   UserSyntax gHC_BOOL (fsLit "Bool") boolTyConKey boolTyCon
157 falseDataConName  = mkWiredInDataConName UserSyntax gHC_BOOL (fsLit "False") falseDataConKey falseDataCon
158 trueDataConName   = mkWiredInDataConName UserSyntax gHC_BOOL (fsLit "True")  trueDataConKey  trueDataCon 
159 listTyConName     = mkWiredInTyConName   BuiltInSyntax gHC_BASE (fsLit "[]") listTyConKey listTyCon
160 nilDataConName    = mkWiredInDataConName BuiltInSyntax gHC_BASE (fsLit "[]") nilDataConKey nilDataCon 
161 consDataConName   = mkWiredInDataConName BuiltInSyntax gHC_BASE (fsLit ":") consDataConKey consDataCon
162
163 floatTyConName     = mkWiredInTyConName   UserSyntax gHC_FLOAT (fsLit "Float") floatTyConKey floatTyCon
164 floatDataConName   = mkWiredInDataConName UserSyntax gHC_FLOAT (fsLit "F#") floatDataConKey floatDataCon
165 doubleTyConName    = mkWiredInTyConName   UserSyntax gHC_FLOAT (fsLit "Double") doubleTyConKey doubleTyCon
166 doubleDataConName  = mkWiredInDataConName UserSyntax gHC_FLOAT (fsLit "D#") doubleDataConKey doubleDataCon
167
168 parrTyConName     = mkWiredInTyConName   BuiltInSyntax gHC_PARR (fsLit "[::]") parrTyConKey parrTyCon 
169 parrDataConName   = mkWiredInDataConName UserSyntax    gHC_PARR (fsLit "PArr") parrDataConKey parrDataCon
170
171 boolTyCon_RDR   = nameRdrName boolTyConName
172 false_RDR       = nameRdrName falseDataConName
173 true_RDR        = nameRdrName trueDataConName
174 intTyCon_RDR    = nameRdrName intTyConName
175 charTyCon_RDR   = nameRdrName charTyConName
176 intDataCon_RDR  = nameRdrName intDataConName
177 listTyCon_RDR   = nameRdrName listTyConName
178 consDataCon_RDR = nameRdrName consDataConName
179 parrTyCon_RDR   = nameRdrName parrTyConName
180 {-
181 tySuperKindTyCon_RDR     = nameRdrName tySuperKindTyConName
182 coSuperKindTyCon_RDR = nameRdrName coSuperKindTyConName
183 liftedTypeKindTyCon_RDR   = nameRdrName liftedTypeKindTyConName
184 openTypeKindTyCon_RDR     = nameRdrName openTypeKindTyConName
185 unliftedTypeKindTyCon_RDR = nameRdrName unliftedTypeKindTyConName
186 ubxTupleKindTyCon_RDR     = nameRdrName ubxTupleKindTyConName
187 argTypeKindTyCon_RDR      = nameRdrName argTypeKindTyConName
188 funKindTyCon_RDR          = nameRdrName funKindTyConName
189 -}
190 \end{code}
191
192
193 %************************************************************************
194 %*                                                                      *
195 \subsection{mkWiredInTyCon}
196 %*                                                                      *
197 %************************************************************************
198
199 \begin{code}
200 pcNonRecDataTyCon = pcTyCon False NonRecursive
201 pcRecDataTyCon    = pcTyCon False Recursive
202
203 pcTyCon is_enum is_rec name tyvars cons
204   = tycon
205   where
206     tycon = mkAlgTyCon name
207                 (mkArrowKinds (map tyVarKind tyvars) liftedTypeKind)
208                 tyvars
209                 []              -- No stupid theta
210                 (DataTyCon cons is_enum)
211                 []              -- No record selectors
212                 NoParentTyCon
213                 is_rec
214                 True            -- All the wired-in tycons have generics
215                 False           -- Not in GADT syntax
216
217 pcDataCon :: Name -> [TyVar] -> [Type] -> TyCon -> DataCon
218 pcDataCon = pcDataConWithFixity False
219
220 pcDataConWithFixity :: Bool -> Name -> [TyVar] -> [Type] -> TyCon -> DataCon
221 -- The Name should be in the DataName name space; it's the name
222 -- of the DataCon itself.
223 --
224 -- The unique is the first of two free uniques;
225 -- the first is used for the datacon itself,
226 -- the second is used for the "worker name"
227
228 pcDataConWithFixity declared_infix dc_name tyvars arg_tys tycon
229   = data_con
230   where
231     data_con = mkDataCon dc_name declared_infix
232                 (map (const NotMarkedStrict) arg_tys)
233                 []      -- No labelled fields
234                 tyvars
235                 []      -- No existential type variables
236                 []      -- No equality spec
237                 []      -- No theta
238                 arg_tys tycon
239                 []      -- No stupid theta
240                 (mkDataConIds bogus_wrap_name wrk_name data_con)
241                 
242
243     mod      = nameModule dc_name
244     wrk_occ  = mkDataConWorkerOcc (nameOccName dc_name)
245     wrk_key  = incrUnique (nameUnique dc_name)
246     wrk_name = mkWiredInName mod wrk_occ wrk_key
247                              (AnId (dataConWorkId data_con)) UserSyntax
248     bogus_wrap_name = pprPanic "Wired-in data wrapper id" (ppr dc_name)
249         -- Wired-in types are too simple to need wrappers
250 \end{code}
251
252
253 %************************************************************************
254 %*                                                                      *
255 \subsection[TysWiredIn-tuples]{The tuple types}
256 %*                                                                      *
257 %************************************************************************
258
259 \begin{code}
260 tupleTyCon :: Boxity -> Arity -> TyCon
261 tupleTyCon boxity i | i > mAX_TUPLE_SIZE = fst (mk_tuple boxity i)      -- Build one specially
262 tupleTyCon Boxed   i = fst (boxedTupleArr   ! i)
263 tupleTyCon Unboxed i = fst (unboxedTupleArr ! i)
264
265 tupleCon :: Boxity -> Arity -> DataCon
266 tupleCon boxity i | i > mAX_TUPLE_SIZE = snd (mk_tuple boxity i)        -- Build one specially
267 tupleCon Boxed   i = snd (boxedTupleArr   ! i)
268 tupleCon Unboxed i = snd (unboxedTupleArr ! i)
269
270 boxedTupleArr, unboxedTupleArr :: Array Int (TyCon,DataCon)
271 boxedTupleArr   = listArray (0,mAX_TUPLE_SIZE) [mk_tuple Boxed i | i <- [0..mAX_TUPLE_SIZE]]
272 unboxedTupleArr = listArray (0,mAX_TUPLE_SIZE) [mk_tuple Unboxed i | i <- [0..mAX_TUPLE_SIZE]]
273
274 mk_tuple :: Boxity -> Int -> (TyCon,DataCon)
275 mk_tuple boxity arity = (tycon, tuple_con)
276   where
277         tycon   = mkTupleTyCon tc_name tc_kind arity tyvars tuple_con boxity gen_info 
278         mod     = mkTupleModule boxity arity
279         tc_name = mkWiredInName mod (mkTupleOcc tcName boxity arity) tc_uniq
280                                 (ATyCon tycon) BuiltInSyntax
281         tc_kind = mkArrowKinds (map tyVarKind tyvars) res_kind
282         res_kind | isBoxed boxity = liftedTypeKind
283                  | otherwise      = ubxTupleKind
284
285         tyvars   | isBoxed boxity = take arity alphaTyVars
286                  | otherwise      = take arity openAlphaTyVars
287
288         tuple_con = pcDataCon dc_name tyvars tyvar_tys tycon
289         tyvar_tys = mkTyVarTys tyvars
290         dc_name   = mkWiredInName mod (mkTupleOcc dataName boxity arity) dc_uniq
291                                   (ADataCon tuple_con) BuiltInSyntax
292         tc_uniq   = mkTupleTyConUnique   boxity arity
293         dc_uniq   = mkTupleDataConUnique boxity arity
294         gen_info  = True                -- Tuples all have generics..
295                                         -- hmm: that's a *lot* of code
296
297 unitTyCon     = tupleTyCon Boxed 0
298 unitDataCon   = head (tyConDataCons unitTyCon)
299 unitDataConId = dataConWorkId unitDataCon
300
301 pairTyCon = tupleTyCon Boxed 2
302
303 unboxedSingletonTyCon   = tupleTyCon Unboxed 1
304 unboxedSingletonDataCon = tupleCon   Unboxed 1
305
306 unboxedPairTyCon   = tupleTyCon Unboxed 2
307 unboxedPairDataCon = tupleCon   Unboxed 2
308 \end{code}
309
310 %************************************************************************
311 %*                                                                      *
312 \subsection[TysWiredIn-boxed-prim]{The ``boxed primitive'' types (@Char@, @Int@, etc)}
313 %*                                                                      *
314 %************************************************************************
315
316 \begin{code}
317 charTy = mkTyConTy charTyCon
318
319 charTyCon   = pcNonRecDataTyCon charTyConName [] [charDataCon]
320 charDataCon = pcDataCon charDataConName [] [charPrimTy] charTyCon
321
322 stringTy = mkListTy charTy -- convenience only
323 \end{code}
324
325 \begin{code}
326 intTy = mkTyConTy intTyCon 
327
328 intTyCon = pcNonRecDataTyCon intTyConName [] [intDataCon]
329 intDataCon = pcDataCon intDataConName [] [intPrimTy] intTyCon
330 \end{code}
331
332 \begin{code}
333 floatTy = mkTyConTy floatTyCon
334
335 floatTyCon   = pcNonRecDataTyCon floatTyConName   [] [floatDataCon]
336 floatDataCon = pcDataCon         floatDataConName [] [floatPrimTy] floatTyCon
337 \end{code}
338
339 \begin{code}
340 doubleTy = mkTyConTy doubleTyCon
341
342 doubleTyCon   = pcNonRecDataTyCon doubleTyConName   [] [doubleDataCon]
343 doubleDataCon = pcDataCon         doubleDataConName [] [doublePrimTy] doubleTyCon
344 \end{code}
345
346
347 %************************************************************************
348 %*                                                                      *
349 \subsection[TysWiredIn-Bool]{The @Bool@ type}
350 %*                                                                      *
351 %************************************************************************
352
353 An ordinary enumeration type, but deeply wired in.  There are no
354 magical operations on @Bool@ (just the regular Prelude code).
355
356 {\em BEGIN IDLE SPECULATION BY SIMON}
357
358 This is not the only way to encode @Bool@.  A more obvious coding makes
359 @Bool@ just a boxed up version of @Bool#@, like this:
360 \begin{verbatim}
361 type Bool# = Int#
362 data Bool = MkBool Bool#
363 \end{verbatim}
364
365 Unfortunately, this doesn't correspond to what the Report says @Bool@
366 looks like!  Furthermore, we get slightly less efficient code (I
367 think) with this coding. @gtInt@ would look like this:
368
369 \begin{verbatim}
370 gtInt :: Int -> Int -> Bool
371 gtInt x y = case x of I# x# ->
372             case y of I# y# ->
373             case (gtIntPrim x# y#) of
374                 b# -> MkBool b#
375 \end{verbatim}
376
377 Notice that the result of the @gtIntPrim@ comparison has to be turned
378 into an integer (here called @b#@), and returned in a @MkBool@ box.
379
380 The @if@ expression would compile to this:
381 \begin{verbatim}
382 case (gtInt x y) of
383   MkBool b# -> case b# of { 1# -> e1; 0# -> e2 }
384 \end{verbatim}
385
386 I think this code is a little less efficient than the previous code,
387 but I'm not certain.  At all events, corresponding with the Report is
388 important.  The interesting thing is that the language is expressive
389 enough to describe more than one alternative; and that a type doesn't
390 necessarily need to be a straightforwardly boxed version of its
391 primitive counterpart.
392
393 {\em END IDLE SPECULATION BY SIMON}
394
395 \begin{code}
396 boolTy = mkTyConTy boolTyCon
397
398 boolTyCon = pcTyCon True NonRecursive boolTyConName
399                     [] [falseDataCon, trueDataCon]
400
401 falseDataCon = pcDataCon falseDataConName [] [] boolTyCon
402 trueDataCon  = pcDataCon trueDataConName  [] [] boolTyCon
403
404 falseDataConId = dataConWorkId falseDataCon
405 trueDataConId  = dataConWorkId trueDataCon
406 \end{code}
407
408 %************************************************************************
409 %*                                                                      *
410 \subsection[TysWiredIn-List]{The @List@ type (incl ``build'' magic)}
411 %*                                                                      *
412 %************************************************************************
413
414 Special syntax, deeply wired in, but otherwise an ordinary algebraic
415 data types:
416 \begin{verbatim}
417 data [] a = [] | a : (List a)
418 data () = ()
419 data (,) a b = (,,) a b
420 ...
421 \end{verbatim}
422
423 \begin{code}
424 mkListTy :: Type -> Type
425 mkListTy ty = mkTyConApp listTyCon [ty]
426
427 listTyCon = pcRecDataTyCon listTyConName alpha_tyvar [nilDataCon, consDataCon]
428
429 nilDataCon  = pcDataCon nilDataConName alpha_tyvar [] listTyCon
430 consDataCon = pcDataConWithFixity True {- Declared infix -}
431                consDataConName
432                alpha_tyvar [alphaTy, mkTyConApp listTyCon alpha_ty] listTyCon
433 -- Interesting: polymorphic recursion would help here.
434 -- We can't use (mkListTy alphaTy) in the defn of consDataCon, else mkListTy
435 -- gets the over-specific type (Type -> Type)
436 \end{code}
437
438 %************************************************************************
439 %*                                                                      *
440 \subsection[TysWiredIn-Tuples]{The @Tuple@ types}
441 %*                                                                      *
442 %************************************************************************
443
444 The tuple types are definitely magic, because they form an infinite
445 family.
446
447 \begin{itemize}
448 \item
449 They have a special family of type constructors, of type @TyCon@
450 These contain the tycon arity, but don't require a Unique.
451
452 \item
453 They have a special family of constructors, of type
454 @Id@. Again these contain their arity but don't need a Unique.
455
456 \item
457 There should be a magic way of generating the info tables and
458 entry code for all tuples.
459
460 But at the moment we just compile a Haskell source
461 file\srcloc{lib/prelude/...} containing declarations like:
462 \begin{verbatim}
463 data Tuple0             = Tup0
464 data Tuple2  a b        = Tup2  a b
465 data Tuple3  a b c      = Tup3  a b c
466 data Tuple4  a b c d    = Tup4  a b c d
467 ...
468 \end{verbatim}
469 The print-names associated with the magic @Id@s for tuple constructors
470 ``just happen'' to be the same as those generated by these
471 declarations.
472
473 \item
474 The instance environment should have a magic way to know
475 that each tuple type is an instances of classes @Eq@, @Ix@, @Ord@ and
476 so on. \ToDo{Not implemented yet.}
477
478 \item
479 There should also be a way to generate the appropriate code for each
480 of these instances, but (like the info tables and entry code) it is
481 done by enumeration\srcloc{lib/prelude/InTup?.hs}.
482 \end{itemize}
483
484 \begin{code}
485 mkTupleTy :: Boxity -> Int -> [Type] -> Type
486 mkTupleTy boxity arity tys = mkTyConApp (tupleTyCon boxity arity) tys
487
488 unitTy = mkTupleTy Boxed 0 []
489 \end{code}
490
491 %************************************************************************
492 %*                                                                      *
493 \subsection[TysWiredIn-PArr]{The @[::]@ type}
494 %*                                                                      *
495 %************************************************************************
496
497 Special syntax for parallel arrays needs some wired in definitions.
498
499 \begin{code}
500 -- construct a type representing the application of the parallel array
501 -- constructor 
502 --
503 mkPArrTy    :: Type -> Type
504 mkPArrTy ty  = mkTyConApp parrTyCon [ty]
505
506 -- represents the type constructor of parallel arrays
507 --
508 --  * this must match the definition in `PrelPArr'
509 --
510 -- NB: Although the constructor is given here, it will not be accessible in
511 --     user code as it is not in the environment of any compiled module except
512 --     `PrelPArr'.
513 --
514 parrTyCon :: TyCon
515 parrTyCon  = pcNonRecDataTyCon parrTyConName alpha_tyvar [parrDataCon]
516
517 parrDataCon :: DataCon
518 parrDataCon  = pcDataCon 
519                  parrDataConName 
520                  alpha_tyvar            -- forall'ed type variables
521                  [intPrimTy,            -- 1st argument: Int#
522                   mkTyConApp            -- 2nd argument: Array# a
523                     arrayPrimTyCon 
524                     alpha_ty] 
525                  parrTyCon
526
527 -- check whether a type constructor is the constructor for parallel arrays
528 --
529 isPArrTyCon    :: TyCon -> Bool
530 isPArrTyCon tc  = tyConName tc == parrTyConName
531
532 -- fake array constructors
533 --
534 --  * these constructors are never really used to represent array values;
535 --   however, they are very convenient during desugaring (and, in particular,
536 --   in the pattern matching compiler) to treat array pattern just like
537 --   yet another constructor pattern
538 --
539 parrFakeCon                        :: Arity -> DataCon
540 parrFakeCon i | i > mAX_TUPLE_SIZE  = mkPArrFakeCon  i  -- build one specially
541 parrFakeCon i                       = parrFakeConArr!i
542
543 -- pre-defined set of constructors
544 --
545 parrFakeConArr :: Array Int DataCon
546 parrFakeConArr  = array (0, mAX_TUPLE_SIZE) [(i, mkPArrFakeCon i)   
547                                             | i <- [0..mAX_TUPLE_SIZE]]
548
549 -- build a fake parallel array constructor for the given arity
550 --
551 mkPArrFakeCon       :: Int -> DataCon
552 mkPArrFakeCon arity  = data_con
553   where
554         data_con  = pcDataCon name [tyvar] tyvarTys parrTyCon
555         tyvar     = head alphaTyVars
556         tyvarTys  = replicate arity $ mkTyVarTy tyvar
557         nameStr   = mkFastString ("MkPArr" ++ show arity)
558         name      = mkWiredInName gHC_PARR (mkOccNameFS dataName nameStr) uniq
559                                   (ADataCon data_con) UserSyntax
560         uniq      = mkPArrDataConUnique arity
561
562 -- checks whether a data constructor is a fake constructor for parallel arrays
563 --
564 isPArrFakeCon      :: DataCon -> Bool
565 isPArrFakeCon dcon  = dcon == parrFakeCon (dataConSourceArity dcon)
566 \end{code}
567
568