diff --git a/Examples/skip.hs b/Examples/skip.hs
new file mode 100644
--- /dev/null
+++ b/Examples/skip.hs
@@ -0,0 +1,16 @@
+module Main where
+import Prelude hiding (head)
+import Data.Enumerator
+import Control.Monad.Trans.Class
+
+skip :: Monad m => Enumeratee a a m b
+skip (Continue k) = do
+    x <- head
+    _ <- head -- the one we're skipping
+    case x of
+        Nothing -> return $ Continue k
+        Just y -> do
+            newStep <- lift $ runIteratee $ k $ Chunks [y]
+            skip newStep
+skip step = return step
+
diff --git a/enumerator.cabal b/enumerator.cabal
--- a/enumerator.cabal
+++ b/enumerator.cabal
@@ -1,5 +1,5 @@
 name: enumerator
-version: 0.4.2
+version: 0.4.3
 synopsis: Implementation of Oleg Kiselyov's left-fold enumerators
 license: MIT
 license-file: license.txt
@@ -32,7 +32,7 @@
   build-depends:
       transformers >= 0.2 && < 0.3
     , bytestring >= 0.9 && < 0.10
-    , text >= 0.7 && < 0.11
+    , text >= 0.7 && < 0.12
 
   if impl(ghc >= 6.10)
     build-depends:
diff --git a/hs/Data/Enumerator.hs b/hs/Data/Enumerator.hs
--- a/hs/Data/Enumerator.hs
+++ b/hs/Data/Enumerator.hs
@@ -48,7 +48,10 @@
 	, concatEnums
 	  -- ** Enumeratees
 	, checkDone
+	, checkDoneEx
 	, Data.Enumerator.map
+	, Data.Enumerator.concatMap
+	, Data.Enumerator.mapM
 	, Data.Enumerator.sequence
 	, joinI
 	  -- * Parser combinators
@@ -352,12 +355,22 @@
 -- the inner 'Iteratee' has finished, and if so, to return its output.
 -- 'checkDone' passes its parameter a continuation if the 'Iteratee'
 -- can still consume input, or yields otherwise.
+checkDoneEx :: Monad m =>
+	Stream a' ->
+	((Stream a -> Iteratee a m b) -> Iteratee a' m (Step a m b)) ->
+	Enumeratee a' a m b
+checkDoneEx extra _ (Yield x chunk) = returnI (Yield (Yield x chunk) extra)
+checkDoneEx _ f (Continue k) = f k
+checkDoneEx _ _ (Error err) = throwError err
+{-# INLINE checkDoneEx #-}
+
+-- | @checkDone = checkDoneEx (Chunks [])@
+--
+-- Use this for enumeratees which do not have an input buffer.
 checkDone :: Monad m =>
 	((Stream a -> Iteratee a m b) -> Iteratee a' m (Step a m b)) ->
 	Enumeratee a' a m b
-checkDone _ (Yield x chunk) = return $ Yield x chunk
-checkDone f (Continue k) = f k
-checkDone _ (Error err) = throwError err
+checkDone = checkDoneEx (Chunks [])
 {-# INLINE checkDone #-}
 map :: Monad m => (ao -> ai) -> Enumeratee ao ai m b
 map f = loop where
@@ -365,6 +378,21 @@
 	step k EOF = yield (Continue k) EOF
 	step k (Chunks []) = continue $ step k
 	step k (Chunks xs) = k (Chunks (Prelude.map f xs)) >>== loop
+concatMap :: Monad m => (ao -> [ai]) -> Enumeratee ao ai m b
+concatMap f = loop where
+	loop = checkDone $ continue . step
+	step k EOF = yield (Continue k) EOF
+	step k (Chunks []) = continue $ step k
+	step k (Chunks xs) = k (Chunks (Prelude.concatMap f xs)) >>== loop
+mapM :: Monad m => (ao -> m ai) -> Enumeratee ao ai m b
+mapM f = checkDone (continue . step) where
+	step k EOF = yield (Continue k) EOF
+	step k (Chunks xs) = loop k xs
+	
+	loop k [] = continue (step k)
+	loop k (x:xs) = do
+		fx <- MT.lift (f x)
+		k (Chunks [fx]) >>== checkDoneEx (Chunks xs) (\k' -> loop k' xs)
 sequence :: Monad m => Iteratee ao m ai -> Enumeratee ao ai m b
 sequence i = loop where
 	loop = checkDone check
diff --git a/hs/Data/Enumerator/Text.hs b/hs/Data/Enumerator/Text.hs
--- a/hs/Data/Enumerator/Text.hs
+++ b/hs/Data/Enumerator/Text.hs
@@ -107,7 +107,7 @@
 decode codec = loop B.empty where
 	dec = codecDecode codec
 	
-	loop acc = checkDone $ continue . step acc
+	loop acc = checkDoneEx (Chunks [acc]) (continue . step acc)
 	step acc k EOF = yield (Continue k) $ if B.null acc
 		then EOF
 		else Chunks [acc]
