diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+1.4.0
+
+* BREAKING CHANGE: Change type of `premapM` to accept a monadic function
+
 1.3.7
 
 * Add `groupBy`
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# `foldl` v1.3.7
+# `foldl` v1.4.0
 
 Use this `foldl` library when you want to compute multiple folds over a
 collection in one pass over the data without space leaks.
diff --git a/foldl.cabal b/foldl.cabal
--- a/foldl.cabal
+++ b/foldl.cabal
@@ -1,5 +1,5 @@
 Name: foldl
-Version: 1.3.7
+Version: 1.4.0
 Cabal-Version: >=1.8.0.2
 Build-Type: Simple
 License: BSD3
diff --git a/src/Control/Foldl.hs b/src/Control/Foldl.hs
--- a/src/Control/Foldl.hs
+++ b/src/Control/Foldl.hs
@@ -371,7 +371,9 @@
 
 instance Monad m => Profunctor (FoldM m) where
     rmap = fmap
-    lmap = premapM
+    lmap f (FoldM step begin done) = FoldM step' begin done
+      where
+        step' x a = step x (f a)
 
 instance (Monoid b, Monad m) => Semigroup (FoldM m a b) where
     (<>) = liftA2 mappend
@@ -982,17 +984,17 @@
 > impurely Pipes.Prelude.foldM
 >     :: Monad m => FoldM m a b -> Producer a m () -> m b
 
-    Other streaming libraries supporting 'purely' and 'impurely' include @io-streams@ and @streaming@. 
+    Other streaming libraries supporting 'purely' and 'impurely' include @io-streams@ and @streaming@.
     So for example we have:
 
-> purely System.IO.Streams.fold_ 
+> purely System.IO.Streams.fold_
 >     :: Fold a b -> Streams.InputStream a -> IO b
 >
-> impurely System.IO.Streams.foldM_ 
+> impurely System.IO.Streams.foldM_
 >     :: FoldM IO a b -> Streams.InputStream a -> IO b
 
-    The @monotraversable@ package makes it convenient to apply a 
-    'Fold' or 'FoldM' to pure containers that do not allow 
+    The @monotraversable@ package makes it convenient to apply a
+    'Fold' or 'FoldM' to pure containers that do not allow
     a general 'Foldable' instance, like unboxed vectors:
 
 > purely ofoldlUnwrap
@@ -1117,20 +1119,18 @@
 {-| @(premapM f folder)@ returns a new 'FoldM' where f is applied to each input
     element
 
-> foldM (premapM f folder) list = foldM folder (map f list)
-
-> premapM id = id
+> premapM return = id
 >
-> premapM (f . g) = premap g . premap f
+> premapM (f <=< g) = premap g . premap f
 
 > premapM k (pure r) = pure r
 >
 > premapM k (f <*> x) = premapM k f <*> premapM k x
 -}
-premapM :: (a -> b) -> FoldM m b r -> FoldM m a r
+premapM :: Monad m => (a -> m b) -> FoldM m b r -> FoldM m a r
 premapM f (FoldM step begin done) = FoldM step' begin done
   where
-    step' x a = step x (f a)
+    step' x a = f a >>= step x
 {-# INLINABLE premapM #-}
 
 {-| @(prefilter f folder)@ returns a new 'Fold' where the folder's input is used
