Improve newtype deriving
authorsimonpj@microsoft.com <unknown>
Sun, 2 Apr 2006 21:59:11 +0000 (21:59 +0000)
committersimonpj@microsoft.com <unknown>
Sun, 2 Apr 2006 21:59:11 +0000 (21:59 +0000)
Ross Paterson pointed out a useful generalisation of GHC's
newtype-deriving mechanism.  This implements it.  The idea
is to allow
newtype Wrap m a = Wrap (m a) deriving (Monad, Eq)
where the representation type doesn't start with a type
constructor.

Actually GHC already *did* implement this, but the eta-ok
check in TcDeriv missed a case, so there was a lurking bug.

This patches fixes the documentation too.  drvrun019 tests.

compiler/typecheck/TcDeriv.lhs
docs/users_guide/glasgow_exts.xml

index 472ce6b..c31e6aa 100644 (file)
@@ -44,8 +44,8 @@ import TyCon          ( tyConTyVars, tyConDataCons, tyConArity, tyConHasGenerics,
                          isEnumerationTyCon, isRecursiveTyCon, TyCon
                        )
 import TcType          ( TcType, ThetaType, mkTyVarTys, mkTyConApp, tcTyConAppTyCon,
-                         isUnLiftedType, mkClassPred, tyVarsOfTypes, isArgTypeKind,
-                         tcEqTypes, tcSplitAppTys, mkAppTys )
+                         isUnLiftedType, mkClassPred, tyVarsOfType,
+                         isArgTypeKind, tcEqTypes, tcSplitAppTys, mkAppTys )
 import Var             ( TyVar, tyVarKind, varName )
 import VarSet          ( mkVarSet, subVarSet )
 import PrelNames
@@ -419,7 +419,8 @@ makeDerivEqns overlap_flag tycl_decls
        args_to_drop   = drop n_args_to_keep rep_ty_args
        args_to_keep   = take n_args_to_keep rep_ty_args
 
-       rep_tys  = tys ++ [mkAppTys rep_fn args_to_keep]
+       rep_fn'  = mkAppTys rep_fn args_to_keep
+       rep_tys  = tys ++ [rep_fn']
        rep_pred = mkClassPred clas rep_tys
                -- rep_pred is the representation dictionary, from where
                -- we are gong to get all the methods for the newtype dictionary
@@ -494,7 +495,7 @@ makeDerivEqns overlap_flag tycl_decls
        --      (b) the remaining type args mention 
        --          only the remaining type variables
        eta_ok = (args_to_drop `tcEqTypes` mkTyVarTys tyvars_to_drop)
-             && (tyVarsOfTypes args_to_keep `subVarSet` mkVarSet tyvars_to_keep) 
+             && (tyVarsOfType rep_fn' `subVarSet` mkVarSet tyvars_to_keep) 
 
        cant_derive_err = derivingThingErr clas tys tycon tyvars_to_keep
                                (vcat [ptext SLIT("even with cunning newtype deriving:"),
index dd410c8..c1dca22 100644 (file)
@@ -3742,20 +3742,17 @@ Derived instance declarations are constructed as follows. Consider the
 declaration (after expansion of any type synonyms)
 
 <programlisting> 
-  newtype T v1...vn = T' (S t1...tk vk+1...vn) deriving (c1...cm) 
+  newtype T v1...vn = T' (t vk+1...vn) deriving (c1...cm) 
 </programlisting> 
 
 where 
  <itemizedlist>
 <listitem><para>
-  <literal>S</literal> is a type constructor, 
+  The type <literal>t</literal> is an arbitrary type
 </para></listitem>
 <listitem><para>
-  The <literal>t1...tk</literal> are types,
-</para></listitem>
-<listitem><para>
-  The <literal>vk+1...vn</literal> are type variables which do not occur in any of
-  the <literal>ti</literal>, and
+  The <literal>vk+1...vn</literal> are type variables which do not occur in 
+  <literal>t</literal>, and
 </para></listitem>
 <listitem><para>
   The <literal>ci</literal> are partial applications of
@@ -3773,7 +3770,7 @@ where
 Then, for each <literal>ci</literal>, the derived instance
 declaration is:
 <programlisting> 
-  instance ci (S t1...tk vk+1...v) => ci (T v1...vp)
+  instance ci (t vk+1...v) => ci (T v1...vp)
 </programlisting>
 where <literal>p</literal> is chosen so that <literal>T v1...vp</literal> is of the 
 right <emphasis>kind</emphasis> for the last parameter of class <literal>Ci</literal>.