Generalise `Control.Monad.{foldM,foldM_}` to `Foldable` (#9586)
authorHerbert Valerio Riedel <hvr@gnu.org>
Sat, 18 Oct 2014 15:01:11 +0000 (17:01 +0200)
committerHerbert Valerio Riedel <hvr@gnu.org>
Sat, 18 Oct 2014 19:58:38 +0000 (21:58 +0200)
With this change `Control.Monad.foldM` becomes an alias for
`Data.Foldable.foldlM`.

Reviewed By: austin, ekmett

Differential Revision: https://phabricator.haskell.org/D251

libraries/base/Control/Monad.hs
libraries/base/changelog.md
testsuite/tests/indexed-types/should_fail/T1897b.stderr
testsuite/tests/typecheck/should_compile/T4969.hs

index db46dea..07b011a 100644 (file)
@@ -75,7 +75,7 @@ module Control.Monad
     , (<$!>)
     ) where
 
-import Data.Foldable ( sequence_, msum, mapM_, forM_ )
+import Data.Foldable ( Foldable, sequence_, msum, mapM_, foldlM, forM_ )
 import Data.Functor ( void )
 import Data.Traversable ( forM, mapM, sequence )
 
@@ -156,21 +156,22 @@ function' are not commutative.
 >         f am xm
 
 If right-to-left evaluation is required, the input list should be reversed.
+
+Note: 'foldM' is the same as 'foldlM'
 -}
 
-foldM             :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a
+foldM          :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b
 {-# INLINEABLE foldM #-}
 {-# SPECIALISE foldM :: (a -> b -> IO a) -> a -> [b] -> IO a #-}
 {-# SPECIALISE foldM :: (a -> b -> Maybe a) -> a -> [b] -> Maybe a #-}
-foldM _ a []      =  return a
-foldM f a (x:xs)  =  f a x >>= \fax -> foldM f fax xs
+foldM          = foldlM
 
 -- | Like 'foldM', but discards the result.
-foldM_            :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m ()
+foldM_         :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m ()
 {-# INLINEABLE foldM_ #-}
 {-# SPECIALISE foldM_ :: (a -> b -> IO a) -> a -> [b] -> IO () #-}
 {-# SPECIALISE foldM_ :: (a -> b -> Maybe a) -> a -> [b] -> Maybe () #-}
-foldM_ f a xs     = foldM f a xs >> return ()
+foldM_ f a xs  = foldlM f a xs >> return ()
 
 -- | @'replicateM' n act@ performs the action @n@ times,
 -- gathering the results.
index 52a076b..ed93b46 100644 (file)
@@ -69,6 +69,8 @@
   * Generalise `Control.Monad.{when,unless,guard}` from `Monad` to
     `Applicative` and from `MonadPlus` to `Alternative` respectively.
 
+  * Generalise `Control.Monad.{foldM,foldM_}` to `Foldable`
+
   * New module `Data.OldList` containing only list-specialised versions of
     the functions from `Data.List` (in other words, `Data.OldList` corresponds
     to `base-4.7.0.1`'s `Data.List`)
index 6372bd9..785f21a 100644 (file)
@@ -1,14 +1,16 @@
-\r
-T1897b.hs:16:1:\r
-    Could not deduce (Depend a0 ~ Depend a)\r
-    from the context (Bug a)\r
-      bound by the inferred type for ‘isValid’:\r
-                 Bug a => [Depend a] -> Bool\r
-      at T1897b.hs:16:1-41\r
-    NB: ‘Depend’ is a type function, and may not be injective\r
-    The type variable ‘a0’ is ambiguous\r
-    Expected type: [Depend a] -> Bool\r
-      Actual type: [Depend a0] -> Bool\r
-    When checking that ‘isValid’ has the inferred type\r
-      isValid :: forall a. Bug a => [Depend a] -> Bool\r
-    Probable cause: the inferred type is ambiguous\r
+
+T1897b.hs:16:1:
+    Could not deduce (Depend a0 ~ Depend a)
+    from the context (Bug a, Foldable t)
+      bound by the inferred type for ‘isValid’:
+                 (Bug a, Foldable t) => t (Depend a) -> Bool
+      at T1897b.hs:16:1-41
+    NB: ‘Depend’ is a type function, and may not be injective
+    The type variable ‘a0’ is ambiguous
+    Expected type: t (Depend a) -> Bool
+      Actual type: t (Depend a0) -> Bool
+    When checking that ‘isValid’ has the inferred type
+      isValid :: forall a (t :: * -> *).
+                 (Bug a, Foldable t) =>
+                 t (Depend a) -> Bool
+    Probable cause: the inferred type is ambiguous
index 2bdd4a7..e35b37e 100644 (file)
@@ -63,7 +63,7 @@ instance ToAbstract LetDef [ALetBinding] where
                                undefined
         where letToAbstract = do
                   localToAbstract lhsArgs $ \args ->
-                          foldM lambda undefined undefined
+                          foldM lambda undefined (undefined :: [a])
               lambda _ _ = do x <- freshNoName undefined
                               return undefined
               lambda _ _ = typeError $ NotAValidLetBinding d