+Generating selector bindings for record delarations
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+\begin{code}
+tcRecordSelectors :: TyCon -> TcM s ([Id], TcHsBinds s)
+tcRecordSelectors tycon
+ = mapAndUnzipTc (tcRecordSelector tycon) groups `thenTc` \ (ids, binds) ->
+ returnTc (ids, SingleBind (NonRecBind (foldr AndMonoBinds EmptyMonoBinds 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 record selector that looks like this:
+
+ data T a b c = T1 { op :: a, ...}
+ | T2 { op :: a, ...}
+ | T3
+
+ sel :: forall a b c. T a b c -> a
+ sel = /\ a b c -> \ T1 { sel = x } -> x
+ T2 { sel = 2 } -> x
+
+Note that the selector Id itself is used as the field
+label; it has to be an Id, you see!
+
+\begin{code}
+tcRecordSelector tycon fields@((first_con, first_field_label) : other_fields)
+ = panic "tcRecordSelector: don't typecheck"
+{-
+ = let
+ field_ty = fieldLabelType first_field_label
+ field_name = fieldLabelName first_field_label
+ other_tys = [fieldLabelType fl | (_, fl) <- fields]
+ (tyvars, _, _, _) = dataConSig first_con
+ -- tyvars of first_con may be free in first_ty
+ in
+
+ -- Check that all the fields in the group have the same type
+ -- This check assumes that all the constructors of a given
+ -- data type use the same type variables
+ checkTc (all (eqTy field_ty) other_tys)
+ (fieldTypeMisMatch field_name) `thenTc_`
+
+ -- Create an Id for the field itself
+ tcInstTyVars tyvars `thenNF_Tc` \ (tyvars', tyvar_tys, tenv) ->
+ tcInstType tenv field_ty `thenNF_Tc` \ field_ty' ->
+ let
+ data_ty' = applyTyCon tycon tyvar_tys
+ in
+ newLocalId SLIT("x") field_ty' `thenNF_Tc` \ field_id ->
+ newLocalId SLIT("r") data_ty' `thenNF_Tc` \ record_id ->
+
+ -- Now build the selector
+ let
+ tycon_src_loc = getSrcLoc tycon
+
+ selector_ty = mkForAllTys tyvars' $
+ mkFunTy data_ty' $
+ field_ty'
+
+ selector_id = mkRecordSelectorId first_field_label selector_ty
+
+ -- HsSyn is dreadfully verbose for defining the selector!
+ selector_rhs = mkHsTyLam tyvars' $
+ HsLam $
+ PatMatch (VarPat record_id) $
+ GRHSMatch $
+ GRHSsAndBindsOut [OtherwiseGRHS selector_body tycon_src_loc]
+ EmptyBinds field_ty'
+
+ selector_body = HsCase (HsVar record_id) (map mk_match fields) tycon_src_loc
+
+ mk_match (con_id, field_label)
+ = PatMatch (RecPat con_id data_ty' [(selector_id, VarPat field_id, False)]) $
+ GRHSMatch $
+ GRHSsAndBindsOut [OtherwiseGRHS (HsVar field_id)
+ (getSrcLoc (fieldLabelName field_label))]
+ EmptyBinds
+ field_ty'
+ in
+ returnTc (selector_id, VarMonoBind selector_id selector_rhs)
+-}
+\end{code}