diff --git a/compiler/prelude/PrelNames.lhs b/compiler/prelude/PrelNames.lhs
index 4bb0e54cf2552af78111694e700fb864f45bb930..1d3a7f9d9bbe7e5b0ed67bd9b777ebf54e649c12 100644
--- a/compiler/prelude/PrelNames.lhs
+++ b/compiler/prelude/PrelNames.lhs
@@ -347,7 +347,7 @@ gHC_PRIM, gHC_TYPES, gHC_GENERICS,
     gHC_MAGIC,
     gHC_CLASSES, gHC_BASE, gHC_ENUM, gHC_GHCI, gHC_CSTRING,
     gHC_SHOW, gHC_READ, gHC_NUM, gHC_INTEGER_TYPE, gHC_LIST,
-    gHC_TUPLE, dATA_TUPLE, dATA_EITHER, dATA_STRING, dATA_FOLDABLE, dATA_TRAVERSABLE,
+    gHC_TUPLE, dATA_TUPLE, dATA_EITHER, dATA_STRING, dATA_FOLDABLE, dATA_TRAVERSABLE, dATA_MONOID,
     gHC_CONC, gHC_IO, gHC_IO_Exception,
     gHC_ST, gHC_ARR, gHC_STABLE, gHC_PTR, gHC_ERR, gHC_REAL,
     gHC_FLOAT, gHC_TOP_HANDLER, sYSTEM_IO, dYNAMIC, tYPEABLE, tYPEABLE_INTERNAL, gENERICS,
@@ -375,6 +375,7 @@ dATA_EITHER     = mkBaseModule (fsLit "Data.Either")
 dATA_STRING     = mkBaseModule (fsLit "Data.String")
 dATA_FOLDABLE   = mkBaseModule (fsLit "Data.Foldable")
 dATA_TRAVERSABLE= mkBaseModule (fsLit "Data.Traversable")
+dATA_MONOID     = mkBaseModule (fsLit "Data.Monoid")
 gHC_CONC        = mkBaseModule (fsLit "GHC.Conc")
 gHC_IO          = mkBaseModule (fsLit "GHC.IO")
 gHC_IO_Exception = mkBaseModule (fsLit "GHC.IO.Exception")
@@ -677,12 +678,16 @@ rightAssocDataCon_RDR = dataQual_RDR gHC_GENERICS (fsLit "RightAssociative")
 notAssocDataCon_RDR   = dataQual_RDR gHC_GENERICS (fsLit "NotAssociative")
 
 
-fmap_RDR, pure_RDR, ap_RDR, foldable_foldr_RDR, traverse_RDR :: RdrName
+fmap_RDR, pure_RDR, ap_RDR, foldable_foldr_RDR, foldMap_RDR,
+    traverse_RDR, mempty_RDR, mappend_RDR :: RdrName
 fmap_RDR                = varQual_RDR gHC_BASE (fsLit "fmap")
 pure_RDR                = varQual_RDR cONTROL_APPLICATIVE (fsLit "pure")
 ap_RDR                  = varQual_RDR cONTROL_APPLICATIVE (fsLit "<*>")
 foldable_foldr_RDR      = varQual_RDR dATA_FOLDABLE       (fsLit "foldr")
+foldMap_RDR             = varQual_RDR dATA_FOLDABLE       (fsLit "foldMap")
 traverse_RDR            = varQual_RDR dATA_TRAVERSABLE    (fsLit "traverse")
+mempty_RDR              = varQual_RDR dATA_MONOID         (fsLit "mempty")
+mappend_RDR             = varQual_RDR dATA_MONOID         (fsLit "mappend")
 
 ----------------------
 varQual_RDR, tcQual_RDR, clsQual_RDR, dataQual_RDR
diff --git a/compiler/typecheck/TcGenDeriv.lhs b/compiler/typecheck/TcGenDeriv.lhs
index 241862c409c93d71a14c823b6913edf2bd40b98a..c643c6b7ecb8b161627390d03448fcbdbd17ae33 100644
--- a/compiler/typecheck/TcGenDeriv.lhs
+++ b/compiler/typecheck/TcGenDeriv.lhs
@@ -1454,11 +1454,11 @@ instance for T is:
       fmap f (T1 x1 x2) = T1 ($(fmap 'a 'b1) x1) ($(fmap 'a 'a) x2)
       fmap f (T2 x1)    = T2 ($(fmap 'a '(T a)) x1)
 
-  $(fmap 'a 'b)         x  =  x     -- when b does not contain a
-  $(fmap 'a 'a)         x  =  f x
-  $(fmap 'a '(b1,b2))   x  =  case x of (x1,x2) -> ($(fmap 'a 'b1) x1, $(fmap 'a 'b2) x2)
-  $(fmap 'a '(T b1 b2)) x  =  fmap $(fmap 'a 'b2) x   -- when a only occurs in the last parameter, b2
-  $(fmap 'a '(b -> c))  x  =  \b -> $(fmap 'a' 'c) (x ($(cofmap 'a 'b) b))
+  $(fmap 'a 'b)          =  \x -> x     -- when b does not contain a
+  $(fmap 'a 'a)          =  f
+  $(fmap 'a '(b1,b2))    =  \x -> case x of (x1,x2) -> ($(fmap 'a 'b1) x1, $(fmap 'a 'b2) x2)
+  $(fmap 'a '(T b1 b2))  =  fmap $(fmap 'a 'b2)   -- when a only occurs in the last parameter, b2
+  $(fmap 'a '(b -> c))   =  \x b -> $(fmap 'a' 'c) (x ($(cofmap 'a 'b) b))
 
 For functions, the type parameter 'a can occur in a contravariant position,
 which means we need to derive a function like:
@@ -1467,12 +1467,12 @@ which means we need to derive a function like:
 
 This is pretty much the same as $fmap, only without the $(cofmap 'a 'a) case:
 
-  $(cofmap 'a 'b)         x  =  x     -- when b does not contain a
-  $(cofmap 'a 'a)         x  =  error "type variable in contravariant position"
-  $(cofmap 'a '(b1,b2))   x  =  case x of (x1,x2) -> ($(cofmap 'a 'b1) x1, $(cofmap 'a 'b2) x2)
-  $(cofmap 'a '[b])       x  =  map $(cofmap 'a 'b) x
-  $(cofmap 'a '(T b1 b2)) x  =  fmap $(cofmap 'a 'b2) x   -- when a only occurs in the last parameter, b2
-  $(cofmap 'a '(b -> c))  x  =  \b -> $(cofmap 'a' 'c) (x ($(fmap 'a 'c) b))
+  $(cofmap 'a 'b)          =  \x -> x     -- when b does not contain a
+  $(cofmap 'a 'a)          =  error "type variable in contravariant position"
+  $(cofmap 'a '(b1,b2))    =  \x -> case x of (x1,x2) -> ($(cofmap 'a 'b1) x1, $(cofmap 'a 'b2) x2)
+  $(cofmap 'a '[b])        =  map $(cofmap 'a 'b)
+  $(cofmap 'a '(T b1 b2))  =  fmap $(cofmap 'a 'b2)   -- when a only occurs in the last parameter, b2
+  $(cofmap 'a '(b -> c))   =  \x b -> $(cofmap 'a' 'c) (x ($(fmap 'a 'c) b))
 
 \begin{code}
 gen_Functor_binds :: SrcSpan -> TyCon -> (LHsBinds RdrName, BagDerivStuff)
@@ -1482,30 +1482,34 @@ gen_Functor_binds loc tycon
     data_cons = tyConDataCons tycon
     fmap_bind = L loc $ mkRdrFunBind (L loc fmap_RDR) eqns
 
-    fmap_eqn con = evalState (match_for_con [f_Pat] con parts) bs_RDRs
+    fmap_eqn con = evalState (match_for_con [f_Pat] con =<< parts) bs_RDRs
       where
-        parts = foldDataConArgs ft_fmap con
+        parts = sequence $ foldDataConArgs ft_fmap con
 
     eqns | null data_cons = [mkSimpleMatch [nlWildPat, nlWildPat]
                                            (error_Expr "Void fmap")]
          | otherwise      = map fmap_eqn data_cons
 
-    ft_fmap :: FFoldType (LHsExpr RdrName -> State [RdrName] (LHsExpr RdrName))
-    -- Tricky higher order type; I can't say I fully understand this code :-(
-    ft_fmap = FT { ft_triv = \x -> return x                    -- fmap f x = x
-                 , ft_var  = \x -> return (nlHsApp f_Expr x)   -- fmap f x = f x
-                 , ft_fun = \g h x -> mkSimpleLam (\b -> h =<< (nlHsApp x `fmap` g b))
-                                                               -- fmap f x = \b -> h (x (g b))
-                 , ft_tup = mkSimpleTupleCase match_for_con    -- fmap f x = case x of (a1,a2,..) -> (g1 a1,g2 a2,..)
-                 , ft_ty_app = \_ g  x -> do gg <- mkSimpleLam g      -- fmap f x = fmap g x
-                                             return $ nlHsApps fmap_RDR [gg,x]
-                 , ft_forall = \_ g  x -> g x
+    ft_fmap :: FFoldType (State [RdrName] (LHsExpr RdrName))
+    ft_fmap = FT { ft_triv = mkSimpleLam $ \x -> return x    -- fmap f = \x -> x
+                 , ft_var  = return f_Expr                   -- fmap f = f
+                 , ft_fun  = \g h -> do                      -- fmap f = \x b -> h (x (g b))
+                                 gg <- g
+                                 hh <- h
+                                 mkSimpleLam2 $ \x b -> return $ nlHsApp hh (nlHsApp x (nlHsApp gg b)) 
+                 , ft_tup = \t gs -> do                      -- fmap f = \x -> case x of (a1,a2,..) -> (g1 a1,g2 a2,..)
+                                 gg <- sequence gs
+                                 mkSimpleLam $ mkSimpleTupleCase match_for_con t gg
+                 , ft_ty_app = \_ g -> nlHsApp fmap_Expr <$> g  -- fmap f = fmap g
+                 , ft_forall = \_ g -> g
                  , ft_bad_app = panic "in other argument"
                  , ft_co_var = panic "contravariant" }
 
+    -- Con a1 a2 ... -> Con (f1 a1) (f2 a2) ...
+    match_for_con :: [LPat RdrName] -> DataCon -> [LHsExpr RdrName]
+                  -> State [RdrName] (LMatch RdrName (LHsExpr RdrName))
     match_for_con = mkSimpleConMatch $
-        \con_name xsM -> do xs <- sequence xsM
-                            return (nlHsApps con_name xs)  -- Con (g1 v1) (g2 v2) ..
+        \con_name xs -> return $ nlHsApps con_name xs  -- Con x1 x2 ..
 \end{code}
 
 Utility functions related to Functor deriving.
@@ -1574,7 +1578,8 @@ deepSubtypesContaining tv
   = functorLikeTraverse tv
         (FT { ft_triv = []
             , ft_var = []
-            , ft_fun = (++), ft_tup = \_ xs -> concat xs
+            , ft_fun = (++)
+            , ft_tup = \_ xs -> concat xs
             , ft_ty_app = (:)
             , ft_bad_app = panic "in other argument"
             , ft_co_var = panic "contravariant"
@@ -1608,19 +1613,22 @@ mkSimpleLam2 lam = do
     return (mkHsLam [nlVarPat n1,nlVarPat n2] body)
 
 -- "Con a1 a2 a3 -> fold [x1 a1, x2 a2, x3 a3]"
-mkSimpleConMatch :: Monad m => (RdrName -> [a] -> m (LHsExpr RdrName)) -> [LPat RdrName]
-                 -> DataCon -> [LHsExpr RdrName -> a] -> m (LMatch RdrName (LHsExpr RdrName))
+mkSimpleConMatch :: Monad m => (RdrName -> [LHsExpr RdrName] -> m (LHsExpr RdrName))
+                 -> [LPat RdrName]
+                 -> DataCon
+                 -> [LHsExpr RdrName]
+                 -> m (LMatch RdrName (LHsExpr RdrName))
 mkSimpleConMatch fold extra_pats con insides = do
     let con_name = getRdrName con
     let vars_needed = takeList insides as_RDRs
     let pat = nlConVarPat con_name vars_needed
-    rhs <- fold con_name (zipWith ($) insides (map nlHsVar vars_needed))
+    rhs <- fold con_name (zipWith nlHsApp insides (map nlHsVar vars_needed))
     return $ mkMatch (extra_pats ++ [pat]) rhs emptyLocalBinds
 
 -- "case x of (a1,a2,a3) -> fold [x1 a1, x2 a2, x3 a3]"
-mkSimpleTupleCase :: Monad m => ([LPat RdrName] -> DataCon -> [LHsExpr RdrName -> a]
-                  -> m (LMatch RdrName (LHsExpr RdrName)))
-                  -> TupleSort -> [LHsExpr RdrName -> a] -> LHsExpr RdrName -> m (LHsExpr RdrName)
+mkSimpleTupleCase :: Monad m => ([LPat RdrName] -> DataCon -> [a]
+                                 -> m (LMatch RdrName (LHsExpr RdrName)))
+                  -> TupleSort -> [a] -> LHsExpr RdrName -> m (LHsExpr RdrName)
 mkSimpleTupleCase match_for_con sort insides x = do
     let con = tupleCon sort (length insides)
     match <- match_for_con [] con insides
@@ -1646,10 +1654,10 @@ Here the derived instance for the type T above is:
 
 The cases are:
 
-  $(foldr 'a 'b)         x z  =  z     -- when b does not contain a
-  $(foldr 'a 'a)         x z  =  f x z
-  $(foldr 'a '(b1,b2))   x z  =  case x of (x1,x2) -> $(foldr 'a 'b1) x1 ( $(foldr 'a 'b2) x2 z )
-  $(foldr 'a '(T b1 b2)) x z  =  foldr $(foldr 'a 'b2) x z  -- when a only occurs in the last parameter, b2
+  $(foldr 'a 'b)         =  \x z -> z     -- when b does not contain a
+  $(foldr 'a 'a)         =  f
+  $(foldr 'a '(b1,b2))   =  \x z -> case x of (x1,x2) -> $(foldr 'a 'b1) x1 ( $(foldr 'a 'b2) x2 z )
+  $(foldr 'a '(T b1 b2)) =  \x z -> foldr $(foldr 'a 'b2) z x  -- when a only occurs in the last parameter, b2
 
 Note that the arguments to the real foldr function are the wrong way around,
 since (f :: a -> b -> b), while (foldr f :: b -> t a -> b).
@@ -1657,28 +1665,51 @@ since (f :: a -> b -> b), while (foldr f :: b -> t a -> b).
 \begin{code}
 gen_Foldable_binds :: SrcSpan -> TyCon -> (LHsBinds RdrName, BagDerivStuff)
 gen_Foldable_binds loc tycon
-  = (unitBag foldr_bind, emptyBag)
+  = (listToBag [foldr_bind, foldMap_bind], emptyBag)
   where
     data_cons = tyConDataCons tycon
 
     foldr_bind = L loc $ mkRdrFunBind (L loc foldable_foldr_RDR) eqns
     eqns = map foldr_eqn data_cons
-    foldr_eqn con = evalState (match_for_con z_Expr [f_Pat,z_Pat] con parts) bs_RDRs
+    foldr_eqn con = evalState (match_foldr z_Expr [f_Pat,z_Pat] con =<< parts) bs_RDRs
       where
-        parts = foldDataConArgs ft_foldr con
-
-    ft_foldr :: FFoldType (LHsExpr RdrName -> LHsExpr RdrName -> State [RdrName] (LHsExpr RdrName))
-    ft_foldr = FT { ft_triv = \_ z -> return z                        -- foldr f z x = z
-                  , ft_var  = \x z -> return (nlHsApps f_RDR [x,z])   -- foldr f z x = f x z
-                  , ft_tup = \b gs x z -> mkSimpleTupleCase (match_for_con z) b gs x
-                  , ft_ty_app = \_ g  x z -> do gg <- mkSimpleLam2 g   -- foldr f z x = foldr (\xx zz -> g xx zz) z x
-                                                return $ nlHsApps foldable_foldr_RDR [gg,z,x]
-                  , ft_forall = \_ g  x z -> g x z
-                  , ft_co_var = panic "covariant"
-                  , ft_fun = panic "function"
+        parts = sequence $ foldDataConArgs ft_foldr con
+
+    foldMap_bind = L loc $ mkRdrFunBind (L loc foldMap_RDR) (map foldMap_eqn data_cons)
+    foldMap_eqn con = evalState (match_foldMap [f_Pat] con =<< parts) bs_RDRs
+      where
+        parts = sequence $ foldDataConArgs ft_foldMap con
+
+    ft_foldr :: FFoldType (State [RdrName] (LHsExpr RdrName))
+    ft_foldr = FT { ft_triv    = mkSimpleLam2 $ \_ z -> return z       -- foldr f = \x z -> z
+                  , ft_var     = return f_Expr                         -- foldr f = f
+                  , ft_tup     = \t g -> do gg <- sequence g           -- foldr f = (\x z -> case x of ...)
+                                            mkSimpleLam2 $ \x z -> mkSimpleTupleCase (match_foldr z) t gg x
+                  , ft_ty_app  = \_ g -> do gg <- g                    -- foldr f = (\x z -> foldr g z x)
+                                            mkSimpleLam2 $ \x z -> return $ nlHsApps foldable_foldr_RDR [gg,z,x]
+                  , ft_forall  = \_ g -> g
+                  , ft_co_var  = panic "contravariant"
+                  , ft_fun     = panic "function"
                   , ft_bad_app = panic "in other argument" }
 
-    match_for_con z = mkSimpleConMatch (\_con_name -> foldrM ($) z) -- g1 v1 (g2 v2 (.. z))
+    match_foldr z = mkSimpleConMatch $ \_con_name xs -> return $ foldr nlHsApp z xs -- g1 v1 (g2 v2 (.. z))
+
+    ft_foldMap :: FFoldType (State [RdrName] (LHsExpr RdrName))
+    ft_foldMap = FT { ft_triv = mkSimpleLam $ \_ -> return mempty_Expr  -- foldMap f = \x -> mempty
+                    , ft_var  = return f_Expr                           -- foldMap f = f
+                    , ft_tup  = \t g -> do gg <- sequence g             -- foldMap f = \x -> case x of (..,)
+                                           mkSimpleLam $ mkSimpleTupleCase match_foldMap t gg
+                    , ft_ty_app = \_ g -> nlHsApp foldMap_Expr <$> g    -- foldMap f = foldMap g
+                    , ft_forall = \_ g -> g
+                    , ft_co_var = panic "contravariant"
+                    , ft_fun = panic "function"
+                    , ft_bad_app = panic "in other argument" }
+    
+    match_foldMap = mkSimpleConMatch $ \_con_name xs -> return $
+        case xs of
+            [] -> mempty_Expr
+            xs -> foldr1 (\x y -> nlHsApps mappend_RDR [x,y]) xs
+
 \end{code}
 
 
@@ -1694,10 +1725,10 @@ Again, Traversable is much like Functor and Foldable.
 
 The cases are:
 
-  $(traverse 'a 'b)         x  =  pure x     -- when b does not contain a
-  $(traverse 'a 'a)         x  =  f x
-  $(traverse 'a '(b1,b2))   x  =  case x of (x1,x2) -> (,) <$> $(traverse 'a 'b1) x1 <*> $(traverse 'a 'b2) x2
-  $(traverse 'a '(T b1 b2)) x  =  traverse $(traverse 'a 'b2) x  -- when a only occurs in the last parameter, b2
+  $(traverse 'a 'b)          =  pure     -- when b does not contain a
+  $(traverse 'a 'a)          =  f
+  $(traverse 'a '(b1,b2))    =  \x -> case x of (x1,x2) -> (,) <$> $(traverse 'a 'b1) x1 <*> $(traverse 'a 'b2) x2
+  $(traverse 'a '(T b1 b2))  =  traverse $(traverse 'a 'b2)  -- when a only occurs in the last parameter, b2
 
 Note that the generated code is not as efficient as it could be. For instance:
 
@@ -1715,26 +1746,26 @@ gen_Traversable_binds loc tycon
 
     traverse_bind = L loc $ mkRdrFunBind (L loc traverse_RDR) eqns
     eqns = map traverse_eqn data_cons
-    traverse_eqn con = evalState (match_for_con [f_Pat] con parts) bs_RDRs
+    traverse_eqn con = evalState (match_for_con [f_Pat] con =<< parts) bs_RDRs
       where
-        parts = foldDataConArgs ft_trav con
-
-
-    ft_trav :: FFoldType (LHsExpr RdrName -> State [RdrName] (LHsExpr RdrName))
-    ft_trav = FT { ft_triv = \x -> return (nlHsApps pure_RDR [x])   -- traverse f x = pure x
-                 , ft_var = \x -> return (nlHsApps f_RDR [x])       -- travese f x = f x
-                 , ft_tup = mkSimpleTupleCase match_for_con         -- travese f x z = case x of (a1,a2,..) ->
-                                                                    --                   (,,) <$> g1 a1 <*> g2 a2 <*> ..
-                 , ft_ty_app = \_ g  x -> do gg <- mkSimpleLam g    -- travese f x = travese (\xx -> g xx) x
-                                             return $ nlHsApps traverse_RDR [gg,x]
-                 , ft_forall = \_ g  x -> g x
-                 , ft_co_var = panic "covariant"
-                 , ft_fun = panic "function"
+        parts = sequence $ foldDataConArgs ft_trav con
+
+
+    ft_trav :: FFoldType (State [RdrName] (LHsExpr RdrName))
+    ft_trav = FT { ft_triv    = return pure_Expr                  -- traverse f = pure x
+                 , ft_var     = return f_Expr                     -- traverse f = f x
+                 , ft_tup     = \t gs -> do                       -- traverse f = \x -> case x of (a1,a2,..) ->
+                                    gg <- sequence gs             --                   (,,) <$> g1 a1 <*> g2 a2 <*> ..
+                                    mkSimpleLam $ mkSimpleTupleCase match_for_con t gg
+                 , ft_ty_app  = \_ g -> nlHsApp traverse_Expr <$> g  -- traverse f = travese g
+                 , ft_forall  = \_ g -> g
+                 , ft_co_var  = panic "contravariant"
+                 , ft_fun     = panic "function"
                  , ft_bad_app = panic "in other argument" }
 
+    -- Con a1 a2 ... -> Con <$> g1 a1 <*> g2 a2 <*> ...
     match_for_con = mkSimpleConMatch $
-        \con_name xsM -> do xs <- sequence xsM
-                            return (mkApCon (nlHsVar con_name) xs)
+        \con_name xs -> return $ mkApCon (nlHsVar con_name) xs
 
     -- ((Con <$> x1) <*> x2) <*> ..
     mkApCon con []     = nlHsApps pure_RDR [con]
@@ -2040,7 +2071,7 @@ bs_RDRs         = [ mkVarUnqual (mkFastString ("b"++show i)) | i <- [(1::Int) ..
 cs_RDRs         = [ mkVarUnqual (mkFastString ("c"++show i)) | i <- [(1::Int) .. ] ]
 
 a_Expr, c_Expr, f_Expr, z_Expr, ltTag_Expr, eqTag_Expr, gtTag_Expr,
-    false_Expr, true_Expr :: LHsExpr RdrName
+    false_Expr, true_Expr, fmap_Expr, pure_Expr, mempty_Expr, foldMap_Expr, traverse_Expr :: LHsExpr RdrName
 a_Expr          = nlHsVar a_RDR
 -- b_Expr       = nlHsVar b_RDR
 c_Expr          = nlHsVar c_RDR
@@ -2051,6 +2082,11 @@ eqTag_Expr      = nlHsVar eqTag_RDR
 gtTag_Expr      = nlHsVar gtTag_RDR
 false_Expr      = nlHsVar false_RDR
 true_Expr       = nlHsVar true_RDR
+fmap_Expr       = nlHsVar fmap_RDR
+pure_Expr       = nlHsVar pure_RDR
+mempty_Expr     = nlHsVar mempty_RDR
+foldMap_Expr    = nlHsVar foldMap_RDR
+traverse_Expr   = nlHsVar traverse_RDR
 
 a_Pat, b_Pat, c_Pat, d_Pat, f_Pat, k_Pat, z_Pat :: LPat RdrName
 a_Pat           = nlVarPat a_RDR