-Generating constructor/selector bindings for data declarations
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-\begin{code}
-mkDataBinds :: TyCon -> TcM s ([Id], TcHsBinds s)
-mkDataBinds tycon
- = ASSERT( isDataTyCon tycon )
- mapAndUnzipTc mkConstructor data_cons `thenTc` \ (con_ids, con_binds) ->
- mapAndUnzipTc (mkRecordSelector tycon) groups `thenTc` \ (sel_ids, sel_binds) ->
- returnTc (con_ids ++ sel_ids,
- SingleBind $ NonRecBind $
- foldr AndMonoBinds
- (foldr AndMonoBinds EmptyMonoBinds con_binds)
- con_binds
- )
- where
- data_cons = tyConDataCons tycon
- fields = [ (con, field) | con <- data_cons,
- field <- dataConFieldLabels con
- ]
-
- -- groups is list of fields that share a common name
- groups = equivClasses cmp_name fields
- cmp_name (_, field1) (_, field2)
- = fieldLabelName field1 `cmp` fieldLabelName field2
-\end{code}
-
-We're going to build a constructor that looks like:
-
- data (Data a, C b) => T a b = T1 !a !Int b
-
- T1 = /\ a b ->
- \d1::Data a, d2::C b ->
- \p q r -> case p of { p ->
- case q of { q ->
- HsCon [a,b,c] [p,q,r]}}
-
-Notice that
-
-* d2 is thrown away --- a context in a data decl is used to make sure
- one *could* construct dictionaries at the site the constructor
- is used, but the dictionary isn't actually used.
-
-* We have to check that we can construct Data dictionaries for
- the types a and Int. Once we've done that we can throw d1 away too.
-
-* We use (case p of ...) to evaluate p, rather than "seq" because
- all that matters is that the arguments are evaluated. "seq" is
- very careful to preserve evaluation order, which we don't need
- to be here.
-