Reorganisation of the source tree
[ghc-hetmet.git] / ghc / compiler / basicTypes / DataCon.lhs
diff --git a/ghc/compiler/basicTypes/DataCon.lhs b/ghc/compiler/basicTypes/DataCon.lhs
deleted file mode 100644 (file)
index 805ef73..0000000
+++ /dev/null
@@ -1,632 +0,0 @@
-%
-% (c) The GRASP/AQUA Project, Glasgow University, 1998
-%
-\section[DataCon]{@DataCon@: Data Constructors}
-
-\begin{code}
-module DataCon (
-       DataCon, DataConIds(..),
-       ConTag, fIRST_TAG,
-       mkDataCon,
-       dataConRepType, dataConSig, dataConName, dataConTag, dataConTyCon,
-       dataConTyVars, dataConResTys,
-       dataConStupidTheta, 
-       dataConInstArgTys, dataConOrigArgTys, dataConInstResTy,
-       dataConInstOrigArgTys, dataConRepArgTys, 
-       dataConFieldLabels, dataConFieldType,
-       dataConStrictMarks, dataConExStricts,
-       dataConSourceArity, dataConRepArity,
-       dataConIsInfix,
-       dataConWorkId, dataConWrapId, dataConWrapId_maybe, dataConImplicitIds,
-       dataConRepStrictness,
-       isNullarySrcDataCon, isNullaryRepDataCon, isTupleCon, isUnboxedTupleCon,
-       isVanillaDataCon, classDataCon, 
-
-       splitProductType_maybe, splitProductType,
-    ) where
-
-#include "HsVersions.h"
-
-import Type            ( Type, ThetaType, substTyWith, substTy, zipOpenTvSubst,
-                         mkForAllTys, mkFunTys, mkTyConApp,
-                         splitTyConApp_maybe, 
-                         mkPredTys, isStrictPred, pprType
-                       )
-import TyCon           ( TyCon, FieldLabel, tyConDataCons, 
-                         isProductTyCon, isTupleTyCon, isUnboxedTupleTyCon )
-import Class           ( Class, classTyCon )
-import Name            ( Name, NamedThing(..), nameUnique )
-import Var             ( TyVar, Id )
-import BasicTypes      ( Arity, StrictnessMark(..) )
-import Outputable
-import Unique          ( Unique, Uniquable(..) )
-import ListSetOps      ( assoc )
-import Util            ( zipEqual, zipWithEqual )
-import Maybes           ( expectJust )
-\end{code}
-
-
-Data constructor representation
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Consider the following Haskell data type declaration
-
-       data T = T !Int ![Int]
-
-Using the strictness annotations, GHC will represent this as
-
-       data T = T Int# [Int]
-
-That is, the Int has been unboxed.  Furthermore, the Haskell source construction
-
-       T e1 e2
-
-is translated to
-
-       case e1 of { I# x -> 
-       case e2 of { r ->
-       T x r }}
-
-That is, the first argument is unboxed, and the second is evaluated.  Finally,
-pattern matching is translated too:
-
-       case e of { T a b -> ... }
-
-becomes
-
-       case e of { T a' b -> let a = I# a' in ... }
-
-To keep ourselves sane, we name the different versions of the data constructor
-differently, as follows.
-
-
-Note [Data Constructor Naming]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Each data constructor C has two, and possibly three, Names associated with it:
-
-                            OccName    Name space      Used for
-  ---------------------------------------------------------------------------
-  * The "source data con"      C       DataName        The DataCon itself
-  * The "real data con"                C       VarName         Its worker Id
-  * The "wrapper data con"     $WC     VarName         Wrapper Id (optional)
-
-Each of these three has a distinct Unique.  The "source data con" name
-appears in the output of the renamer, and names the Haskell-source
-data constructor.  The type checker translates it into either the wrapper Id
-(if it exists) or worker Id (otherwise).
-
-The data con has one or two Ids associated with it:
-
-  The "worker Id", is the actual data constructor.
-       Its type may be different to the Haskell source constructor
-       because:
-               - useless dict args are dropped
-               - strict args may be flattened
-       The worker is very like a primop, in that it has no binding.
-
-       Newtypes have no worker Id
-
-
-  The "wrapper Id", $WC, whose type is exactly what it looks like
-       in the source program. It is an ordinary function,
-       and it gets a top-level binding like any other function.
-
-       The wrapper Id isn't generated for a data type if the worker
-       and wrapper are identical.  It's always generated for a newtype.
-
-
-
-A note about the stupid context
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Data types can have a context:
-       
-       data (Eq a, Ord b) => T a b = T1 a b | T2 a
-
-and that makes the constructors have a context too
-(notice that T2's context is "thinned"):
-
-       T1 :: (Eq a, Ord b) => a -> b -> T a b
-       T2 :: (Eq a) => a -> T a b
-
-Furthermore, this context pops up when pattern matching
-(though GHC hasn't implemented this, but it is in H98, and
-I've fixed GHC so that it now does):
-
-       f (T2 x) = x
-gets inferred type
-       f :: Eq a => T a b -> a
-
-I say the context is "stupid" because the dictionaries passed
-are immediately discarded -- they do nothing and have no benefit.
-It's a flaw in the language.
-
-       Up to now [March 2002] I have put this stupid context into the
-       type of the "wrapper" constructors functions, T1 and T2, but
-       that turned out to be jolly inconvenient for generics, and
-       record update, and other functions that build values of type T
-       (because they don't have suitable dictionaries available).
-
-       So now I've taken the stupid context out.  I simply deal with
-       it separately in the type checker on occurrences of a
-       constructor, either in an expression or in a pattern.
-
-       [May 2003: actually I think this decision could evasily be
-       reversed now, and probably should be.  Generics could be
-       disabled for types with a stupid context; record updates now
-       (H98) needs the context too; etc.  It's an unforced change, so
-       I'm leaving it for now --- but it does seem odd that the
-       wrapper doesn't include the stupid context.]
-
-[July 04] With the advent of generalised data types, it's less obvious
-what the "stupid context" is.  Consider
-       C :: forall a. Ord a => a -> a -> T (Foo a)
-Does the C constructor in Core contain the Ord dictionary?  Yes, it must:
-
-       f :: T b -> Ordering
-       f = /\b. \x:T b. 
-           case x of
-               C a (d:Ord a) (p:a) (q:a) -> compare d p q
-
-Note that (Foo a) might not be an instance of Ord.
-
-%************************************************************************
-%*                                                                     *
-\subsection{Data constructors}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-data DataCon
-  = MkData {
-       dcName    :: Name,      -- This is the name of the *source data con*
-                               -- (see "Note [Data Constructor Naming]" above)
-       dcUnique :: Unique,     -- Cached from Name
-       dcTag    :: ConTag,
-
-       -- Running example:
-       --
-       --      data Eq a => T a = forall b. Ord b => MkT a [b]
-
-       -- The next six fields express the type of the constructor, in pieces
-       -- e.g.
-       --
-       --      dcTyVars      = [a,b]
-       --      dcStupidTheta = [Eq a]
-       --      dcTheta       = [Ord b]
-       --      dcOrigArgTys  = [a,List b]
-       --      dcTyCon       = T
-       --      dcTyArgs      = [a,b]
-
-       dcVanilla :: Bool,      -- True <=> This is a vanilla Haskell 98 data constructor
-                               --          Its type is of form
-                               --              forall a1..an . t1 -> ... tm -> T a1..an
-                               --          No existentials, no GADTs, nothing.
-                               --
-                               -- NB1: the order of the forall'd variables does matter;
-                               --      for a vanilla constructor, we assume that if the result
-                               --      type is (T t1 ... tn) then we can instantiate the constr
-                               --      at types [t1, ..., tn]
-                               --
-                               -- NB2: a vanilla constructor can still be declared in GADT-style 
-                               --      syntax, provided its type looks like the above.
-
-       dcTyVars :: [TyVar],    -- Universally-quantified type vars 
-                               -- for the data constructor.
-               -- See NB1 on dcVanilla for the conneciton between dcTyVars and dcResTys
-               -- 
-               -- In general, the dcTyVars are NOT NECESSARILY THE SAME AS THE TYVARS
-               -- FOR THE PARENT TyCon. With GADTs the data con might not even have 
-               -- the same number of type variables.
-               -- [This is a change (Oct05): previously, vanilla datacons guaranteed to
-               --  have the same type variables as their parent TyCon, but that seems ugly.]
-
-       dcStupidTheta  ::  ThetaType,   -- This is a "thinned" version of 
-                                       -- the context of the data decl.  
-               -- "Thinned", because the Report says
-               -- to eliminate any constraints that don't mention
-               -- tyvars free in the arg types for this constructor
-               --
-               -- "Stupid", because the dictionaries aren't used for anything.  
-               -- 
-               -- Indeed, [as of March 02] they are no 
-               -- longer in the type of the wrapper Id, because
-               -- that makes it harder to use the wrap-id to rebuild
-               -- values after record selection or in generics.
-               --
-               -- Fact: the free tyvars of dcStupidTheta are a subset of
-               --       the free tyvars of dcResTys
-               -- Reason: dcStupidTeta is gotten by instantiating the 
-               --         stupid theta from the tycon (see BuildTyCl.mkDataConStupidTheta)
-
-       dcTheta  :: ThetaType,          -- The existentially quantified stuff
-                                       
-       dcOrigArgTys :: [Type],         -- Original argument types
-                                       -- (before unboxing and flattening of
-                                       --  strict fields)
-
-       -- Result type of constructor is T t1..tn
-       dcTyCon  :: TyCon,              -- Result tycon, T
-       dcResTys :: [Type],             -- Result type args, t1..tn
-
-       -- Now the strictness annotations and field labels of the constructor
-       dcStrictMarks :: [StrictnessMark],
-               -- Strictness annotations as decided by the compiler.  
-               -- Does *not* include the existential dictionaries
-               -- length = dataConSourceArity dataCon
-
-       dcFields  :: [FieldLabel],
-               -- Field labels for this constructor, in the
-               -- same order as the argument types; 
-               -- length = 0 (if not a record) or dataConSourceArity.
-
-       -- Constructor representation
-       dcRepArgTys :: [Type],          -- Final, representation argument types, 
-                                       -- after unboxing and flattening,
-                                       -- and *including* existential dictionaries
-
-       dcRepStrictness :: [StrictnessMark],    -- One for each *representation* argument       
-
-       dcRepType   :: Type,    -- Type of the constructor
-                               --      forall a b . Ord b => a -> [b] -> MkT a
-                               -- (this is *not* of the constructor wrapper Id:
-                               --  see notes after this data type declaration)
-                               --
-       -- Notice that the existential type parameters come *second*.  
-       -- Reason: in a case expression we may find:
-       --      case (e :: T t) of { MkT b (d:Ord b) (x:t) (xs:[b]) -> ... }
-       -- It's convenient to apply the rep-type of MkT to 't', to get
-       --      forall b. Ord b => ...
-       -- and use that to check the pattern.  Mind you, this is really only
-       -- use in CoreLint.
-
-
-       -- Finally, the curried worker function that corresponds to the constructor
-       -- It doesn't have an unfolding; the code generator saturates these Ids
-       -- and allocates a real constructor when it finds one.
-       --
-       -- An entirely separate wrapper function is built in TcTyDecls
-       dcIds :: DataConIds,
-
-       dcInfix :: Bool         -- True <=> declared infix
-                               -- Used for Template Haskell and 'deriving' only
-                               -- The actual fixity is stored elsewhere
-  }
-
-data DataConIds
-  = NewDC Id                   -- Newtypes have only a wrapper, but no worker
-  | AlgDC (Maybe Id) Id        -- Algebraic data types always have a worker, and
-                               -- may or may not have a wrapper, depending on whether
-                               -- the wrapper does anything.
-
-       -- _Neither_ the worker _nor_ the wrapper take the dcStupidTheta dicts as arguments
-
-       -- The wrapper takes dcOrigArgTys as its arguments
-       -- The worker takes dcRepArgTys as its arguments
-       -- If the worker is absent, dcRepArgTys is the same as dcOrigArgTys
-
-       -- The 'Nothing' case of AlgDC is important
-       -- Not only is this efficient,
-       -- but it also ensures that the wrapper is replaced
-       -- by the worker (becuase it *is* the wroker)
-       -- even when there are no args. E.g. in
-       --              f (:) x
-       -- the (:) *is* the worker.
-       -- This is really important in rule matching,
-       -- (We could match on the wrappers,
-       -- but that makes it less likely that rules will match
-       -- when we bring bits of unfoldings together.)
-
-type ConTag = Int
-
-fIRST_TAG :: ConTag
-fIRST_TAG =  1 -- Tags allocated from here for real constructors
-\end{code}
-
-The dcRepType field contains the type of the representation of a contructor
-This may differ from the type of the contructor *Id* (built
-by MkId.mkDataConId) for two reasons:
-       a) the constructor Id may be overloaded, but the dictionary isn't stored
-          e.g.    data Eq a => T a = MkT a a
-
-       b) the constructor may store an unboxed version of a strict field.
-
-Here's an example illustrating both:
-       data Ord a => T a = MkT Int! a
-Here
-       T :: Ord a => Int -> a -> T a
-but the rep type is
-       Trep :: Int# -> a -> T a
-Actually, the unboxed part isn't implemented yet!
-
-
-%************************************************************************
-%*                                                                     *
-\subsection{Instances}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-instance Eq DataCon where
-    a == b = getUnique a == getUnique b
-    a /= b = getUnique a /= getUnique b
-
-instance Ord DataCon where
-    a <= b = getUnique a <= getUnique b
-    a <         b = getUnique a <  getUnique b
-    a >= b = getUnique a >= getUnique b
-    a >         b = getUnique a > getUnique b
-    compare a b = getUnique a `compare` getUnique b
-
-instance Uniquable DataCon where
-    getUnique = dcUnique
-
-instance NamedThing DataCon where
-    getName = dcName
-
-instance Outputable DataCon where
-    ppr con = ppr (dataConName con)
-
-instance Show DataCon where
-    showsPrec p con = showsPrecSDoc p (ppr con)
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
-\subsection{Construction}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-mkDataCon :: Name 
-         -> Bool       -- Declared infix
-         -> Bool       -- Vanilla (see notes with dcVanilla)
-         -> [StrictnessMark] -> [FieldLabel]
-         -> [TyVar] -> ThetaType -> ThetaType
-         -> [Type] -> TyCon -> [Type]
-         -> DataConIds
-         -> DataCon
-  -- Can get the tag from the TyCon
-
-mkDataCon name declared_infix vanilla
-         arg_stricts   -- Must match orig_arg_tys 1-1
-         fields
-         tyvars stupid_theta theta orig_arg_tys tycon res_tys
-         ids
-  = con
-  where
-    con = MkData {dcName = name, 
-                 dcUnique = nameUnique name, dcVanilla = vanilla,
-                 dcTyVars = tyvars, dcStupidTheta = stupid_theta, dcTheta = theta,
-                 dcOrigArgTys = orig_arg_tys, dcTyCon = tycon, dcResTys = res_tys,
-                 dcRepArgTys = rep_arg_tys,
-                 dcStrictMarks = arg_stricts, dcRepStrictness = rep_arg_stricts,
-                 dcFields = fields, dcTag = tag, dcRepType = ty,
-                 dcIds = ids, dcInfix = declared_infix}
-
-       -- Strictness marks for source-args
-       --      *after unboxing choices*, 
-       -- but  *including existential dictionaries*
-       -- 
-       -- The 'arg_stricts' passed to mkDataCon are simply those for the
-       -- source-language arguments.  We add extra ones for the
-       -- dictionary arguments right here.
-    dict_tys     = mkPredTys theta
-    real_arg_tys = dict_tys                      ++ orig_arg_tys
-    real_stricts = map mk_dict_strict_mark theta ++ arg_stricts
-
-       -- Representation arguments and demands
-    (rep_arg_stricts, rep_arg_tys) = computeRep real_stricts real_arg_tys
-
-    tag = assoc "mkDataCon" (tyConDataCons tycon `zip` [fIRST_TAG..]) con
-    ty  = mkForAllTys tyvars (mkFunTys rep_arg_tys result_ty)
-               -- NB: the existential dict args are already in rep_arg_tys
-
-    result_ty = mkTyConApp tycon res_tys
-
-mk_dict_strict_mark pred | isStrictPred pred = MarkedStrict
-                        | otherwise         = NotMarkedStrict
-\end{code}
-
-\begin{code}
-dataConName :: DataCon -> Name
-dataConName = dcName
-
-dataConTag :: DataCon -> ConTag
-dataConTag  = dcTag
-
-dataConTyCon :: DataCon -> TyCon
-dataConTyCon = dcTyCon
-
-dataConRepType :: DataCon -> Type
-dataConRepType = dcRepType
-
-dataConIsInfix :: DataCon -> Bool
-dataConIsInfix = dcInfix
-
-dataConTyVars :: DataCon -> [TyVar]
-dataConTyVars = dcTyVars
-
-dataConWorkId :: DataCon -> Id
-dataConWorkId dc = case dcIds dc of
-                       AlgDC _ wrk_id -> wrk_id
-                       NewDC _ -> pprPanic "dataConWorkId" (ppr dc)
-
-dataConWrapId_maybe :: DataCon -> Maybe Id
-dataConWrapId_maybe dc = case dcIds dc of
-                               AlgDC mb_wrap _ -> mb_wrap
-                               NewDC wrap      -> Just wrap
-
-dataConWrapId :: DataCon -> Id
--- Returns an Id which looks like the Haskell-source constructor
-dataConWrapId dc = case dcIds dc of
-                       AlgDC (Just wrap) _   -> wrap
-                       AlgDC Nothing     wrk -> wrk        -- worker=wrapper
-                       NewDC wrap            -> wrap
-
-dataConImplicitIds :: DataCon -> [Id]
-dataConImplicitIds dc = case dcIds dc of
-                         AlgDC (Just wrap) work -> [wrap,work]
-                         AlgDC Nothing     work -> [work]
-                         NewDC wrap             -> [wrap]
-
-dataConFieldLabels :: DataCon -> [FieldLabel]
-dataConFieldLabels = dcFields
-
-dataConFieldType :: DataCon -> FieldLabel -> Type
-dataConFieldType con label = expectJust "unexpected label" $
-    lookup label (dcFields con `zip` dcOrigArgTys con)
-
-dataConStrictMarks :: DataCon -> [StrictnessMark]
-dataConStrictMarks = dcStrictMarks
-
-dataConExStricts :: DataCon -> [StrictnessMark]
--- Strictness of *existential* arguments only
--- Usually empty, so we don't bother to cache this
-dataConExStricts dc = map mk_dict_strict_mark (dcTheta dc)
-
-dataConSourceArity :: DataCon -> Arity
-       -- Source-level arity of the data constructor
-dataConSourceArity dc = length (dcOrigArgTys dc)
-
--- dataConRepArity gives the number of actual fields in the
--- {\em representation} of the data constructor.  This may be more than appear
--- in the source code; the extra ones are the existentially quantified
--- dictionaries
-dataConRepArity (MkData {dcRepArgTys = arg_tys}) = length arg_tys
-
-isNullarySrcDataCon, isNullaryRepDataCon :: DataCon -> Bool
-isNullarySrcDataCon dc = null (dcOrigArgTys dc)
-isNullaryRepDataCon dc = null (dcRepArgTys dc)
-
-dataConRepStrictness :: DataCon -> [StrictnessMark]
-       -- Give the demands on the arguments of a
-       -- Core constructor application (Con dc args)
-dataConRepStrictness dc = dcRepStrictness dc
-
-dataConSig :: DataCon -> ([TyVar], ThetaType,
-                         [Type], TyCon, [Type])
-
-dataConSig (MkData {dcTyVars = tyvars, dcTheta  = theta,
-                   dcOrigArgTys = arg_tys, dcTyCon = tycon, dcResTys = res_tys})
-  = (tyvars, theta, arg_tys, tycon, res_tys)
-
-dataConStupidTheta :: DataCon -> ThetaType
-dataConStupidTheta dc = dcStupidTheta dc
-
-dataConResTys :: DataCon -> [Type]
-dataConResTys dc = dcResTys dc
-
-dataConInstArgTys :: DataCon
-                 -> [Type]     -- Instantiated at these types
-                               -- NB: these INCLUDE the existentially quantified arg types
-                 -> [Type]     -- Needs arguments of these types
-                               -- NB: these INCLUDE the existentially quantified dict args
-                               --     but EXCLUDE the data-decl context which is discarded
-                               -- It's all post-flattening etc; this is a representation type
-dataConInstArgTys (MkData {dcRepArgTys = arg_tys, dcTyVars = tyvars}) inst_tys
- = ASSERT( length tyvars == length inst_tys )
-   map (substTyWith tyvars inst_tys) arg_tys
-
-dataConInstResTy :: DataCon -> [Type] -> Type
-dataConInstResTy (MkData {dcTyVars = tyvars, dcTyCon = tc, dcResTys = res_tys}) inst_tys
- = ASSERT( length tyvars == length inst_tys )
-   substTy (zipOpenTvSubst tyvars inst_tys) (mkTyConApp tc res_tys)
-       -- res_tys can't currently contain any foralls,
-       -- but might in future; hence zipOpenTvSubst
-
--- And the same deal for the original arg tys
-dataConInstOrigArgTys :: DataCon -> [Type] -> [Type]
-dataConInstOrigArgTys (MkData {dcOrigArgTys = arg_tys, dcTyVars = tyvars}) inst_tys
- = ASSERT( length tyvars == length inst_tys )
-   map (substTyWith tyvars inst_tys) arg_tys
-\end{code}
-
-These two functions get the real argument types of the constructor,
-without substituting for any type variables.
-
-dataConOrigArgTys returns the arg types of the wrapper, excluding all dictionary args.
-
-dataConRepArgTys retuns the arg types of the worker, including all dictionaries, and
-after any flattening has been done.
-
-\begin{code}
-dataConOrigArgTys :: DataCon -> [Type]
-dataConOrigArgTys dc = dcOrigArgTys dc
-
-dataConRepArgTys :: DataCon -> [Type]
-dataConRepArgTys dc = dcRepArgTys dc
-\end{code}
-
-
-\begin{code}
-isTupleCon :: DataCon -> Bool
-isTupleCon (MkData {dcTyCon = tc}) = isTupleTyCon tc
-       
-isUnboxedTupleCon :: DataCon -> Bool
-isUnboxedTupleCon (MkData {dcTyCon = tc}) = isUnboxedTupleTyCon tc
-
-isVanillaDataCon :: DataCon -> Bool
-isVanillaDataCon dc = dcVanilla dc
-\end{code}
-
-
-\begin{code}
-classDataCon :: Class -> DataCon
-classDataCon clas = case tyConDataCons (classTyCon clas) of
-                     (dict_constr:no_more) -> ASSERT( null no_more ) dict_constr 
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection{Splitting products}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-splitProductType_maybe
-       :: Type                         -- A product type, perhaps
-       -> Maybe (TyCon,                -- The type constructor
-                 [Type],               -- Type args of the tycon
-                 DataCon,              -- The data constructor
-                 [Type])               -- Its *representation* arg types
-
-       -- Returns (Just ...) for any
-       --      concrete (i.e. constructors visible)
-       --      single-constructor
-       --      not existentially quantified
-       -- type whether a data type or a new type
-       --
-       -- Rejecing existentials is conservative.  Maybe some things
-       -- could be made to work with them, but I'm not going to sweat
-       -- it through till someone finds it's important.
-
-splitProductType_maybe ty
-  = case splitTyConApp_maybe ty of
-       Just (tycon,ty_args)
-          | isProductTyCon tycon       -- Includes check for non-existential,
-                                       -- and for constructors visible
-          -> Just (tycon, ty_args, data_con, dataConInstArgTys data_con ty_args)
-          where
-             data_con = head (tyConDataCons tycon)
-       other -> Nothing
-
-splitProductType str ty
-  = case splitProductType_maybe ty of
-       Just stuff -> stuff
-       Nothing    -> pprPanic (str ++ ": not a product") (pprType ty)
-
-
-computeRep :: [StrictnessMark]         -- Original arg strictness
-          -> [Type]                    -- and types
-          -> ([StrictnessMark],        -- Representation arg strictness
-              [Type])                  -- And type
-
-computeRep stricts tys
-  = unzip $ concat $ zipWithEqual "computeRep" unbox stricts tys
-  where
-    unbox NotMarkedStrict ty = [(NotMarkedStrict, ty)]
-    unbox MarkedStrict    ty = [(MarkedStrict,    ty)]
-    unbox MarkedUnboxed   ty = zipEqual "computeRep" (dataConRepStrictness arg_dc) arg_tys
-                            where
-                              (_, _, arg_dc, arg_tys) = splitProductType "unbox_strict_arg_ty" ty
-\end{code}