diff --git a/enumerator.cabal b/enumerator.cabal
--- a/enumerator.cabal
+++ b/enumerator.cabal
@@ -1,11 +1,11 @@
 name: enumerator
-version: 0.4.15
+version: 0.4.16
 synopsis: Reliable, high-performance processing with left-fold enumerators
 license: MIT
 license-file: license.txt
 author: John Millikin <jmillikin@gmail.com>
 maintainer: jmillikin@gmail.com
-copyright: Copyright (c) John Millikin 2010-2011
+copyright: 2010-2011 John Millikin, 2011 Mikhail Vorozhtsov
 build-type: Simple
 cabal-version: >= 1.6
 category: Data, Enumerator
@@ -121,6 +121,7 @@
   tests/EnumeratorTests/Text/Unfold.hs
   tests/EnumeratorTests/Text/Util.hs
   tests/EnumeratorTests/Text/Zip.hs
+  tests/EnumeratorTests/Trans.hs
   tests/EnumeratorTests/Util.hs
 
 source-repository head
@@ -150,6 +151,7 @@
     Data.Enumerator.IO
     Data.Enumerator.List
     Data.Enumerator.Text
+    Data.Enumerator.Trans
 
   other-modules:
     Data.Enumerator.Compatibility
diff --git a/lib/Data/Enumerator/Binary.hs b/lib/Data/Enumerator/Binary.hs
--- a/lib/Data/Enumerator/Binary.hs
+++ b/lib/Data/Enumerator/Binary.hs
@@ -90,6 +90,7 @@
 	-- ** Unsorted
 	, require
 	, isolate
+	, isolateWhile
 	, splitWhen
 	
 	) where
@@ -688,6 +689,23 @@
 				in k (toChunks s1) >>== (`yield` toChunks s2)
 	loop EOF = k EOF >>== (`yield` EOF)
 isolate n step = drop n >> return step
+
+-- | @'isolateWhile' p@ reads bytes from the stream until /p/ is false, and
+-- passes them to its iteratee. If the iteratee finishes early, bytes
+-- continue to be consumed from the outer stream until /p/ is false.
+--
+-- Since: 0.4.16
+isolateWhile :: Monad m => (Word8 -> Bool) -> Enumeratee B.ByteString B.ByteString m b
+isolateWhile p (Continue k) = continue loop where
+	loop (Chunks []) = continue loop
+	loop (Chunks xs) = iter where
+		lazy = BL.fromChunks xs
+		(s1, s2) = BL.span p lazy
+		iter = if BL.null s2
+			then k (Chunks xs) >>== isolateWhile p
+			else k (toChunks s1) >>== (`yield` toChunks s2)
+	loop EOF = k EOF >>== (`yield` EOF)
+isolateWhile p step = Data.Enumerator.Binary.dropWhile p >> return step
 
 -- | Split on bytes satisfying a given predicate.
 --
diff --git a/lib/Data/Enumerator/List.hs b/lib/Data/Enumerator/List.hs
--- a/lib/Data/Enumerator/List.hs
+++ b/lib/Data/Enumerator/List.hs
@@ -79,6 +79,7 @@
 	-- ** Unsorted
 	, require
 	, isolate
+	, isolateWhile
 	, splitWhen
 	
 	) where
@@ -678,6 +679,20 @@
 			in k (Chunks s1) >>== (`yield` Chunks s2)
 	loop EOF = k EOF >>== (`yield` EOF)
 isolate n step = drop n >> return step
+
+-- | @'isolateWhile' p@ reads elements from the stream until /p/ is false, and
+-- passes them to its iteratee. If the iteratee finishes early, elements
+-- continue to be consumed from the outer stream until /p/ is false.
+--
+-- Since: 0.4.16
+isolateWhile :: Monad m => (a -> Bool) -> Enumeratee a a m b
+isolateWhile p (Continue k) = continue loop where
+	loop (Chunks []) = continue loop
+	loop (Chunks xs) = case Prelude.span p xs of
+		(_, []) -> k (Chunks xs) >>== isolateWhile p
+		(s1, s2) -> k (Chunks s1) >>== (`yield` Chunks s2)
+	loop EOF = k EOF >>== (`yield` EOF)
+isolateWhile p step = Data.Enumerator.List.dropWhile p >> return step
 
 -- | Split on elements satisfying a given predicate.
 --
diff --git a/lib/Data/Enumerator/Text.hs b/lib/Data/Enumerator/Text.hs
--- a/lib/Data/Enumerator/Text.hs
+++ b/lib/Data/Enumerator/Text.hs
@@ -88,6 +88,7 @@
 	-- ** Unsorted
 	, require
 	, isolate
+	, isolateWhile
 	, splitWhen
 	, lines
 	
@@ -709,6 +710,23 @@
 				in k (toChunks s1) >>== (`yield` toChunks s2)
 	loop EOF = k EOF >>== (`yield` EOF)
 isolate n step = drop n >> return step
+
+-- | @'isolateWhile' p@ reads characters from the stream until /p/ is false, and
+-- passes them to its iteratee. If the iteratee finishes early, characters
+-- continue to be consumed from the outer stream until /p/ is false.
+--
+-- Since: 0.4.16
+isolateWhile :: Monad m => (Char -> Bool) -> Enumeratee T.Text T.Text m b
+isolateWhile p (Continue k) = continue loop where
+	loop (Chunks []) = continue loop
+	loop (Chunks xs) = iter where
+		lazy = TL.fromChunks xs
+		(s1, s2) = TL.span p lazy
+		iter = if TL.null s2
+			then k (Chunks xs) >>== isolateWhile p
+			else k (toChunks s1) >>== (`yield` toChunks s2)
+	loop EOF = k EOF >>== (`yield` EOF)
+isolateWhile p step = Data.Enumerator.Text.dropWhile p >> return step
 
 -- | Split on characters satisfying a given predicate.
 --
diff --git a/lib/Data/Enumerator/Trans.hs b/lib/Data/Enumerator/Trans.hs
new file mode 100644
--- /dev/null
+++ b/lib/Data/Enumerator/Trans.hs
@@ -0,0 +1,248 @@
+-- |
+-- Module: Data.Enumerator.Trans
+-- Copyright: 2011 Mikhail Vorozhtsov
+-- License: MIT
+--
+-- Maintainer: jmillikin@gmail.com
+-- Portability: portable
+--
+-- This module provides functions for running monad transformers within
+-- iteratees. Most types defined in the \"transformers\" library are
+-- supported.
+--
+-- Functions suffixed with an apostrophe (@'@) apply to the strict variant
+-- of their transformer type.
+--
+-- Since: 0.4.16
+module Data.Enumerator.Trans
+	(
+	
+	-- * IdentityT
+	  runIdentityI
+	
+	-- * MaybeT
+	, runMaybeI
+	
+	-- * ErrorT
+	, runErrorI
+	
+	-- * ReaderT
+	, runReaderI
+	
+	-- * StateT
+	-- ** Lazy
+	, runStateI
+	, evalStateI
+	-- ** Strict
+	, runStateI'
+	, evalStateI'
+	
+	-- * WriterT
+	-- ** Lazy
+	, runWriterI
+	, execWriterI
+	-- ** Strict
+	, runWriterI'
+	, execWriterI'
+	
+	-- * RWST
+	-- ** Lazy
+	, runRWSI
+	, evalRWSI
+	, execRWSI
+	-- ** Strict
+	, runRWSI'
+	, evalRWSI'
+	, execRWSI'
+	) where
+
+import           Data.Monoid (Monoid(..))
+import           Control.Monad.Trans.Identity
+import           Control.Monad.Trans.Maybe
+import           Control.Monad.Trans.Error
+import           Control.Monad.Trans.Reader
+import qualified Control.Monad.Trans.State.Lazy as L
+import qualified Control.Monad.Trans.State.Strict as S
+import qualified Control.Monad.Trans.Writer.Lazy as L
+import qualified Control.Monad.Trans.Writer.Strict as S
+import qualified Control.Monad.Trans.RWS.Lazy as L
+import qualified Control.Monad.Trans.RWS.Strict as S
+
+import           Data.Enumerator (Stream(..), Step(..), Iteratee(..))
+
+-- | Lifted version of 'runIdentityT'
+--
+-- Since: 0.4.16
+runIdentityI :: Monad m => Iteratee a (IdentityT m) b -> Iteratee a m b
+runIdentityI it = Iteratee $ do
+	step <- runIdentityT $ runIteratee it
+	return $ case step of
+		Continue k -> Continue $ runIdentityI . k
+		Yield x cs -> Yield x cs
+		Error e    -> Error e
+
+-- | Lifted version of 'runMaybeT'
+--
+-- Since: 0.4.16
+runMaybeI :: Monad m => Iteratee a (MaybeT m) b -> Iteratee a m (Maybe b)
+runMaybeI it = Iteratee $ do
+	mStep <- runMaybeT $ runIteratee it
+	return $ case mStep of
+		Nothing   -> Yield Nothing $ Chunks []
+		Just step -> case step of
+			Continue k -> Continue $ runMaybeI . k
+			Yield x cs -> Yield (Just x) cs
+			Error e    -> Error e
+
+-- | Lifted version of 'runErrorT'
+--
+-- Since: 0.4.16
+runErrorI :: (Error e, Monad m)
+          => Iteratee a (ErrorT e m) b -> Iteratee a m (Either e b)
+runErrorI it = Iteratee $ do
+	mStep <- runErrorT $ runIteratee it
+	return $ case mStep of
+		Left e     -> Yield (Left e) $ Chunks []
+		Right step -> case step of
+			Continue k -> Continue $ runErrorI . k
+			Yield x cs -> Yield (Right x) cs
+			Error e    -> Error e
+
+-- | Lifted version of 'runReaderT'
+--
+-- Since: 0.4.16
+runReaderI :: Monad m => r -> Iteratee a (ReaderT r m) b -> Iteratee a m b
+runReaderI r it = Iteratee $ do
+	step <- runReaderT (runIteratee it) r
+	return $ case step of
+		Continue k -> Continue $ runReaderI r . k
+		Yield x cs -> Yield x cs
+		Error e    -> Error e
+
+-- | Lifted version of (lazy) 'L.runStateT'
+--
+-- Since: 0.4.16
+runStateI :: Monad m => s -> Iteratee a (L.StateT s m) b -> Iteratee a m (b, s)
+runStateI s it = Iteratee $ do
+	~(step, s') <- L.runStateT (runIteratee it) s
+	return $ case step of
+		Continue k -> Continue $ runStateI s' . k
+		Yield x cs -> Yield (x, s') cs
+		Error e    -> Error e
+
+-- | Lifted version of (lazy) 'L.evalStateT'
+--
+-- Since: 0.4.16
+evalStateI :: Monad m => s -> Iteratee a (L.StateT s m) b -> Iteratee a m b
+evalStateI s = fmap fst . runStateI s
+
+-- | Lifted version of (strict) 'S.runStateT'
+--
+-- Since: 0.4.16
+runStateI' :: Monad m => s -> Iteratee a (S.StateT s m) b -> Iteratee a m (b, s)
+runStateI' s it = Iteratee $ do
+	(step, s') <- S.runStateT (runIteratee it) s
+	return $ case step of
+		Continue k -> Continue $ runStateI' s' . k
+		Yield x cs -> Yield (x, s') cs
+		Error e    -> Error e
+
+-- | Lifted version of (strict) 'S.evalStateT'
+--
+-- Since: 0.4.16
+evalStateI' :: Monad m => s -> Iteratee a (S.StateT s m) b -> Iteratee a m b
+evalStateI' s = fmap fst . runStateI' s
+
+-- | Lifted version of (lazy) 'L.runWriterT'
+--
+-- Since: 0.4.16
+runWriterI :: (Monoid w, Monad m)
+           => Iteratee a (L.WriterT w m) b -> Iteratee a m (b, w)
+runWriterI it0 = go mempty it0 where
+	go w it = Iteratee $ do
+		~(step, w') <- L.runWriterT $ runIteratee it
+		return $ case step of
+			Continue k -> Continue $ go (w `mappend` w') . k
+			Yield x cs -> Yield (x, w `mappend` w') cs
+			Error e    -> Error e
+
+-- | Lifted version of (lazy) 'L.execWriterT'
+--
+-- Since: 0.4.16
+execWriterI :: (Monoid w, Monad m)
+            => Iteratee a (L.WriterT w m) b -> Iteratee a m w
+execWriterI = fmap snd . runWriterI
+
+-- | Lifted version of (strict) 'S.runWriterT'
+--
+-- Since: 0.4.16
+runWriterI' :: (Monoid w, Monad m)
+            => Iteratee a (S.WriterT w m) b -> Iteratee a m (b, w)
+runWriterI' it0 = go mempty it0 where
+	go w it = Iteratee $ do
+		(step, w') <- S.runWriterT $ runIteratee it
+		return $ case step of
+			Continue k -> Continue $ go (w `mappend` w') . k
+			Yield x cs -> Yield (x, w `mappend` w') cs
+			Error e    -> Error e
+
+-- | Lifted version of (strict) 'L.execWriterT'
+--
+-- Since: 0.4.16
+execWriterI' :: (Monoid w, Monad m)
+             => Iteratee a (S.WriterT w m) b -> Iteratee a m w
+execWriterI' = fmap snd . runWriterI'
+
+-- | Lifted version of (lazy) 'L.runRWST'
+--
+-- Since: 0.4.16
+runRWSI :: (Monoid w, Monad m)
+        => r -> s -> Iteratee a (L.RWST r w s m) b -> Iteratee a m (b, s, w)
+runRWSI r s0 it0 = go s0 mempty it0 where
+	go s w it = Iteratee $ do
+		~(step, s', w') <- L.runRWST (runIteratee it) r s
+		return $ case step of
+			Continue k -> Continue $ go s' (w `mappend` w') . k
+			Yield x cs -> Yield (x, s', w `mappend` w') cs
+			Error e    -> Error e
+
+-- | Lifted version of (lazy) 'L.evalRWST'
+--
+-- Since: 0.4.16
+evalRWSI :: (Monoid w, Monad m)
+         => r -> s -> Iteratee a (L.RWST r w s m) b -> Iteratee a m (b, w)
+evalRWSI r s = fmap (\(x, _, w) -> (x, w)) . runRWSI r s
+
+-- | Lifted version of (lazy) 'L.execRWST'
+--
+-- Since: 0.4.16
+execRWSI :: (Monoid w, Monad m)
+         => r -> s -> Iteratee a (L.RWST r w s m) b -> Iteratee a m (s, w)
+execRWSI r s = fmap (\(_, s', w) -> (s', w)) . runRWSI r s
+
+-- | Lifted version of (strict) 'S.runRWST'
+--
+-- Since: 0.4.16
+runRWSI' :: (Monoid w, Monad m)
+         => r -> s -> Iteratee a (S.RWST r w s m) b -> Iteratee a m (b, s, w)
+runRWSI' r s0 it0 = go s0 mempty it0 where
+	go s w it = Iteratee $ do
+		(step, s', w') <- S.runRWST (runIteratee it) r s
+		return $ case step of
+			Continue k -> Continue $ go s' (w `mappend` w') . k
+			Yield x cs -> Yield (x, s', w `mappend` w') cs
+			Error e    -> Error e
+
+-- | Lifted version of (strict) 'S.evalRWST'
+--
+-- Since: 0.4.16
+evalRWSI' :: (Monoid w, Monad m)
+          => r -> s -> Iteratee a (S.RWST r w s m) b -> Iteratee a m (b, w)
+evalRWSI' r s = fmap (\(x, _, w) -> (x, w)) . runRWSI' r s
+
+-- | Lifted version of (strict) 'S.execRWST'
+--
+-- Since: 0.4.16
+execRWSI' :: (Monoid w, Monad m)
+          => r -> s -> Iteratee a (S.RWST r w s m) b -> Iteratee a m (s, w)
+execRWSI' r s = fmap (\(_, s', w) -> (s', w)) . runRWSI' r s
diff --git a/scripts/run-coverage b/scripts/run-coverage
--- a/scripts/run-coverage
+++ b/scripts/run-coverage
@@ -72,6 +72,7 @@
 --exclude=EnumeratorTests.Text.Unfold \
 --exclude=EnumeratorTests.Text.Util \
 --exclude=EnumeratorTests.Text.Zip \
+--exclude=EnumeratorTests.Trans \
 --exclude=EnumeratorTests.Util"
 
 hpc markup --srcdir=src/ --srcdir=tests/ enumerator_tests.tix --destdir=hpc-markup $EXCLUDES > /dev/null
diff --git a/tests/EnumeratorTests.hs b/tests/EnumeratorTests.hs
--- a/tests/EnumeratorTests.hs
+++ b/tests/EnumeratorTests.hs
@@ -20,6 +20,7 @@
 import           EnumeratorTests.Sequence (test_Sequence)
 import           EnumeratorTests.Stream (test_Stream)
 import           EnumeratorTests.Text (test_Text)
+import           EnumeratorTests.Trans (test_Trans)
 
 tests :: [Suite]
 tests =
@@ -41,6 +42,7 @@
 	, test_Sequence
 	, test_Stream
 	, test_Text
+	, test_Trans
 	, test_TryIO
 	]
 
diff --git a/tests/EnumeratorTests/Binary.hs b/tests/EnumeratorTests/Binary.hs
--- a/tests/EnumeratorTests/Binary.hs
+++ b/tests/EnumeratorTests/Binary.hs
@@ -42,6 +42,7 @@
 	, test_Head
 	, test_Head_
 	, test_Isolate
+	, test_IsolateWhile
 	, test_Iterate
 	, test_IterateM
 	, test_IterHandle
diff --git a/tests/EnumeratorTests/Binary/Isolate.hs b/tests/EnumeratorTests/Binary/Isolate.hs
--- a/tests/EnumeratorTests/Binary/Isolate.hs
+++ b/tests/EnumeratorTests/Binary/Isolate.hs
@@ -6,6 +6,7 @@
 -- See license.txt for details
 module EnumeratorTests.Binary.Isolate
 	( test_Isolate
+	, test_IsolateWhile
 	) where
 
 import qualified Data.ByteString.Lazy as BL
@@ -24,9 +25,9 @@
 test_Isolate :: Suite
 test_Isolate = suite "isolate"
 	[ prop_Isolate
-	, test_DropExtra
-	, test_HandleEOF
-	, test_BadParameter
+	, test_Isolate_DropExtra
+	, test_Isolate_HandleEOF
+	, test_Isolate_BadParameter
 	]
 
 prop_Isolate :: Suite
@@ -40,8 +41,8 @@
 		(x:[]) -> (Just x, BL.empty)
 		(x:_:xs) -> (Just x, BL.pack xs))
 
-test_DropExtra :: Suite
-test_DropExtra = assertions "drop-extra" $ do
+test_Isolate_DropExtra :: Suite
+test_Isolate_DropExtra = assertions "drop-extra" $ do
 	$expect $ equal
 		(Just 0x41, ["C"])
 		(E.runLists_ [[], ["A"], ["B"], ["C"]] $ do
@@ -55,8 +56,8 @@
 			extra <- EL.consume
 			return (x, extra))
 
-test_HandleEOF :: Suite
-test_HandleEOF = assertions "handle-eof" $ do
+test_Isolate_HandleEOF :: Suite
+test_Isolate_HandleEOF = assertions "handle-eof" $ do
 	$expect $ equal
 		(Nothing :: Maybe Word8, [])
 		(E.runLists_ [] $ do
@@ -64,11 +65,41 @@
 			extra <- EL.consume
 			return (x, extra))
 
-test_BadParameter :: Suite
-test_BadParameter = assertions "bad-parameter" $ do
+test_Isolate_BadParameter :: Suite
+test_Isolate_BadParameter = assertions "bad-parameter" $ do
 	$expect $ equal
 		(Nothing, ["A", "B", "C"])
 		(E.runLists_ [["A"], ["B"], ["C"]] $ do
 			x <- EB.isolate 0 =$ EB.head
+			extra <- EL.consume
+			return (x, extra))
+
+test_IsolateWhile :: Suite
+test_IsolateWhile = suite "isolateWhile"
+	[ test_IsolateWhile_DropExtra
+	, test_IsolateWhile_HandleEOF
+	]
+
+test_IsolateWhile_DropExtra :: Suite
+test_IsolateWhile_DropExtra = assertions "drop-extra" $ do
+	$expect $ equal
+		(Just 0x41, ["C"])
+		(E.runLists_ [[], ["A"], ["B"], ["C"]] $ do
+			x <- EB.isolateWhile (< 0x43) =$ EB.head
+			extra <- EL.consume
+			return (x, extra))
+	$expect $ equal
+		(Just 0x41, ["C"])
+		(E.runLists_ [["A", "B", "C"]] $ do
+			x <- EB.isolateWhile (< 0x43) =$ EB.head
+			extra <- EL.consume
+			return (x, extra))
+
+test_IsolateWhile_HandleEOF :: Suite
+test_IsolateWhile_HandleEOF = assertions "handle-eof" $ do
+	$expect $ equal
+		(Nothing :: Maybe Word8, [])
+		(E.runLists_ [] $ do
+			x <- EB.isolateWhile (< 0x43) =$ EB.head
 			extra <- EL.consume
 			return (x, extra))
diff --git a/tests/EnumeratorTests/List.hs b/tests/EnumeratorTests/List.hs
--- a/tests/EnumeratorTests/List.hs
+++ b/tests/EnumeratorTests/List.hs
@@ -40,6 +40,7 @@
 	, test_Head
 	, test_Head_
 	, test_Isolate
+	, test_IsolateWhile
 	, test_Iterate
 	, test_IterateM
 	, test_Map
diff --git a/tests/EnumeratorTests/List/Isolate.hs b/tests/EnumeratorTests/List/Isolate.hs
--- a/tests/EnumeratorTests/List/Isolate.hs
+++ b/tests/EnumeratorTests/List/Isolate.hs
@@ -6,6 +6,7 @@
 -- See license.txt for details
 module EnumeratorTests.List.Isolate
 	( test_Isolate
+	, test_IsolateWhile
 	) where
 
 import           Test.Chell
@@ -20,9 +21,9 @@
 test_Isolate :: Suite
 test_Isolate = suite "isolate"
 	[ prop_Isolate
-	, test_DropExtra
-	, test_HandleEOF
-	, test_BadParameter
+	, test_Isolate_DropExtra
+	, test_Isolate_HandleEOF
+	, test_Isolate_BadParameter
 	]
 
 prop_Isolate :: Suite
@@ -36,8 +37,8 @@
 		(x:[]) -> (Just x, [])
 		(x:_:xs') -> (Just x, xs'))
 
-test_DropExtra :: Suite
-test_DropExtra = assertions "drop-extra" $ do
+test_Isolate_DropExtra :: Suite
+test_Isolate_DropExtra = assertions "drop-extra" $ do
 	$expect $ equal
 		(Just 'A', ['C'])
 		(E.runLists_ [[], ['A'], ['B'], ['C']] $ do
@@ -51,8 +52,8 @@
 			extra <- EL.consume
 			return (x, extra))
 
-test_HandleEOF :: Suite
-test_HandleEOF = assertions "handle-eof" $ do
+test_Isolate_HandleEOF :: Suite
+test_Isolate_HandleEOF = assertions "handle-eof" $ do
 	$expect $ equal
 		(Nothing :: Maybe Char, [])
 		(E.runLists_ [] $ do
@@ -60,11 +61,41 @@
 			extra <- EL.consume
 			return (x, extra))
 
-test_BadParameter :: Suite
-test_BadParameter = assertions "bad-parameter" $ do
+test_Isolate_BadParameter :: Suite
+test_Isolate_BadParameter = assertions "bad-parameter" $ do
 	$expect $ equal
 		(Nothing, ['A', 'B', 'C'])
 		(E.runLists_ [['A'], ['B'], ['C']] $ do
 			x <- EL.isolate 0 =$ EL.head
+			extra <- EL.consume
+			return (x, extra))
+
+test_IsolateWhile :: Suite
+test_IsolateWhile = suite "isolateWhile"
+	[ test_IsolateWhile_DropExtra
+	, test_IsolateWhile_HandleEOF
+	]
+
+test_IsolateWhile_DropExtra :: Suite
+test_IsolateWhile_DropExtra = assertions "drop-extra" $ do
+	$expect $ equal
+		(Just 'A', ['C'])
+		(E.runLists_ [[], ['A'], ['B'], ['C']] $ do
+			x <- EL.isolateWhile (< 'C') =$ EL.head
+			extra <- EL.consume
+			return (x, extra))
+	$expect $ equal
+		(Just 'A', ['C'])
+		(E.runLists_ [['A', 'B', 'C']] $ do
+			x <- EL.isolateWhile (< 'C') =$ EL.head
+			extra <- EL.consume
+			return (x, extra))
+
+test_IsolateWhile_HandleEOF :: Suite
+test_IsolateWhile_HandleEOF = assertions "handle-eof" $ do
+	$expect $ equal
+		(Nothing :: Maybe Char, [])
+		(E.runLists_ [] $ do
+			x <- EL.isolateWhile (< 'C') =$ EL.head
 			extra <- EL.consume
 			return (x, extra))
diff --git a/tests/EnumeratorTests/Text.hs b/tests/EnumeratorTests/Text.hs
--- a/tests/EnumeratorTests/Text.hs
+++ b/tests/EnumeratorTests/Text.hs
@@ -43,6 +43,7 @@
 	, test_Head
 	, test_Head_
 	, test_Isolate
+	, test_IsolateWhile
 	, test_Iterate
 	, test_IterateM
 	, test_IterHandle
diff --git a/tests/EnumeratorTests/Text/Isolate.hs b/tests/EnumeratorTests/Text/Isolate.hs
--- a/tests/EnumeratorTests/Text/Isolate.hs
+++ b/tests/EnumeratorTests/Text/Isolate.hs
@@ -6,6 +6,7 @@
 -- See license.txt for details
 module EnumeratorTests.Text.Isolate
 	( test_Isolate
+	, test_IsolateWhile
 	) where
 
 import qualified Data.Text.Lazy as TL
@@ -23,9 +24,9 @@
 test_Isolate :: Suite
 test_Isolate = suite "isolate"
 	[ prop_Isolate
-	, test_DropExtra
-	, test_HandleEOF
-	, test_BadParameter
+	, test_Isolate_DropExtra
+	, test_Isolate_HandleEOF
+	, test_Isolate_BadParameter
 	]
 
 prop_Isolate :: Suite
@@ -39,8 +40,8 @@
 		(x:[]) -> (Just x, TL.empty)
 		(x:_:xs') -> (Just x, TL.pack xs'))
 
-test_DropExtra :: Suite
-test_DropExtra = assertions "drop-extra" $ do
+test_Isolate_DropExtra :: Suite
+test_Isolate_DropExtra = assertions "drop-extra" $ do
 	$expect $ equal
 		(Just 'A', ["C"])
 		(E.runLists_ [[], ["A"], ["B"], ["C"]] $ do
@@ -54,8 +55,8 @@
 			extra <- EL.consume
 			return (x, extra))
 
-test_HandleEOF :: Suite
-test_HandleEOF = assertions "handle-eof" $ do
+test_Isolate_HandleEOF :: Suite
+test_Isolate_HandleEOF = assertions "handle-eof" $ do
 	$expect $ equal
 		(Nothing :: Maybe Char, [])
 		(E.runLists_ [] $ do
@@ -63,11 +64,41 @@
 			extra <- EL.consume
 			return (x, extra))
 
-test_BadParameter :: Suite
-test_BadParameter = assertions "bad-parameter" $ do
+test_Isolate_BadParameter :: Suite
+test_Isolate_BadParameter = assertions "bad-parameter" $ do
 	$expect $ equal
 		(Nothing, ["A", "B", "C"])
 		(E.runLists_ [["A"], ["B"], ["C"]] $ do
 			x <- ET.isolate 0 =$ ET.head
+			extra <- EL.consume
+			return (x, extra))
+
+test_IsolateWhile :: Suite
+test_IsolateWhile = suite "isolateWhile"
+	[ test_IsolateWhile_DropExtra
+	, test_IsolateWhile_HandleEOF
+	]
+
+test_IsolateWhile_DropExtra :: Suite
+test_IsolateWhile_DropExtra = assertions "drop-extra" $ do
+	$expect $ equal
+		(Just 'A', ["C"])
+		(E.runLists_ [[], ["A"], ["B"], ["C"]] $ do
+			x <- ET.isolateWhile (< 'C') =$ ET.head
+			extra <- EL.consume
+			return (x, extra))
+	$expect $ equal
+		(Just 'A', ["C"])
+		(E.runLists_ [["A", "B", "C"]] $ do
+			x <- ET.isolateWhile (< 'C') =$ ET.head
+			extra <- EL.consume
+			return (x, extra))
+
+test_IsolateWhile_HandleEOF :: Suite
+test_IsolateWhile_HandleEOF = assertions "handle-eof" $ do
+	$expect $ equal
+		(Nothing :: Maybe Char, [])
+		(E.runLists_ [] $ do
+			x <- ET.isolateWhile (< 'C') =$ ET.head
 			extra <- EL.consume
 			return (x, extra))
diff --git a/tests/EnumeratorTests/Trans.hs b/tests/EnumeratorTests/Trans.hs
new file mode 100644
--- /dev/null
+++ b/tests/EnumeratorTests/Trans.hs
@@ -0,0 +1,371 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TemplateHaskell #-}
+
+-- Copyright (C) 2011 John Millikin <jmillikin@gmail.com>
+--
+-- See license.txt for details
+module EnumeratorTests.Trans
+	( test_Trans
+	) where
+
+import           Control.Exception
+import           Control.Monad (mzero)
+import           Control.Monad.Trans.Class (lift)
+import qualified Control.Monad.Trans.Error as ErrorT
+import qualified Control.Monad.Trans.Reader as ReaderT
+import qualified Control.Monad.Trans.State.Lazy as StateT_L
+import qualified Control.Monad.Trans.State.Strict as StateT_S
+import qualified Control.Monad.Trans.Writer.Lazy as WriterT_L
+import qualified Control.Monad.Trans.Writer.Strict as WriterT_S
+import qualified Control.Monad.Trans.RWS.Lazy as RWST_L
+import qualified Control.Monad.Trans.RWS.Strict as RWST_S
+
+import           Test.Chell
+
+import qualified Data.Enumerator as E
+import qualified Data.Enumerator.List as EL
+import qualified Data.Enumerator.Trans as ET
+
+import           EnumeratorTests.Util (equalExc)
+
+test_Trans :: Suite
+test_Trans = suite "transformers"
+	[ test_RunIdentityI
+	, test_RunMaybeI
+	, test_RunErrorI
+	, test_RunReaderI
+	, test_RunStateI
+	, test_EvalStateI
+	, test_RunWriterI
+	, test_ExecWriterI
+	, test_RunRWSI
+	, test_EvalRWSI
+	, test_ExecRWSI
+	]
+
+test_RunIdentityI :: Suite
+test_RunIdentityI = assertions "runIdentityI" $ do
+	$expect $ equal
+		(['a'], ['b'])
+		(E.runLists_ [['a'], ['b']] $ do
+			x <- ET.runIdentityI (EL.take 1)
+			extra <- EL.consume
+			return (x, extra))
+	$expect $ equalExc
+		(ErrorCall "err")
+		(E.runLists [] $ ET.runIdentityI (E.throwError (ErrorCall "err")))
+
+test_RunMaybeI :: Suite
+test_RunMaybeI = assertions "runMaybeI" $ do
+	$expect $ equal
+		(Just ['a'], ['b'])
+		(E.runLists_ [['a'], ['b']] $ do
+			x <- ET.runMaybeI (EL.take 1)
+			extra <- EL.consume
+			return (x, extra))
+	$expect $ equal
+		(Nothing :: Maybe [Char], ['a', 'b'])
+		(E.runLists_ [['a'], ['b']] $ do
+			x <- ET.runMaybeI (lift mzero)
+			extra <- EL.consume
+			return (x, extra))
+	$expect $ equalExc
+		(ErrorCall "err")
+		(E.runLists [] $ ET.runMaybeI (E.throwError (ErrorCall "err")))
+
+test_RunErrorI :: Suite
+test_RunErrorI = assertions "runErrorI" $ do
+	$expect $ equal
+		(Right ['a'] :: Either String [Char], ['b'])
+		(E.runLists_ [['a'], ['b']] $ do
+			x <- ET.runErrorI (EL.take 1)
+			extra <- EL.consume
+			return (x, extra))
+	$expect $ equal
+		(Left "err" :: Either String [Char], ['a', 'b'])
+		(E.runLists_ [['a'], ['b']] $ do
+			x <- ET.runErrorI (lift (ErrorT.throwError "err"))
+			extra <- EL.consume
+			return (x, extra))
+	$expect $ equalExc
+		(ErrorCall "err")
+		(E.runLists [] $ ET.runErrorI $ do
+			_ <- E.throwError (ErrorCall "err")
+			lift (ErrorT.throwError ("err2" :: String)))
+
+test_RunReaderI :: Suite
+test_RunReaderI = assertions "runReaderI" $ do
+	$expect $ equal
+		((['a'], 'A'), ['b'])
+		(E.runLists_ [['a'], ['b']] $ do
+			xy <- ET.runReaderI 'A' $ do
+				x <- EL.take 1
+				y <- lift ReaderT.ask
+				return (x, y)
+			extra <- EL.consume
+			return (xy, extra))
+	$expect $ equalExc
+		(ErrorCall "err")
+		(E.runLists [] $ ET.runReaderI 'A' (E.throwError (ErrorCall "err")))
+
+test_RunStateI :: Suite
+test_RunStateI = suite "runStateI"
+	[ test_RunStateI_Lazy
+	, test_RunStateI_Strict
+	]
+
+test_RunStateI_Lazy :: Suite
+test_RunStateI_Lazy = assertions "lazy" $ do
+	$expect $ equal
+		(((['a'], 'A'), 'B'), ['b'])
+		(E.runLists_ [['a'], ['b']] $ do
+			xy <- ET.runStateI 'A' $ do
+				x <- EL.take 1
+				y <- lift StateT_L.get
+				lift (StateT_L.put 'B')
+				return (x, y)
+			extra <- EL.consume
+			return (xy, extra))
+	$expect $ equalExc
+		(ErrorCall "err")
+		(E.runLists [] $ ET.runStateI 'A' (E.throwError (ErrorCall "err")))
+
+test_RunStateI_Strict :: Suite
+test_RunStateI_Strict = assertions "strict" $ do
+	$expect $ equal
+		(((['a'], 'A'), 'B'), ['b'])
+		(E.runLists_ [['a'], ['b']] $ do
+			xy <- ET.runStateI' 'A' $ do
+				x <- EL.take 1
+				y <- lift StateT_S.get
+				lift (StateT_S.put 'B')
+				return (x, y)
+			extra <- EL.consume
+			return (xy, extra))
+	$expect $ equalExc
+		(ErrorCall "err")
+		(E.runLists [] $ ET.runStateI' 'A' (E.throwError (ErrorCall "err")))
+
+test_EvalStateI :: Suite
+test_EvalStateI = suite "evalStateI"
+	[ test_EvalStateI_Lazy
+	, test_EvalStateI_Strict
+	]
+
+test_EvalStateI_Lazy :: Suite
+test_EvalStateI_Lazy = assertions "lazy" $ do
+	$expect $ equal
+		((['a'], 'A'), ['b'])
+		(E.runLists_ [['a'], ['b']] $ do
+			xy <- ET.evalStateI 'A' $ do
+				x <- EL.take 1
+				y <- lift StateT_L.get
+				lift (StateT_L.put 'B')
+				return (x, y)
+			extra <- EL.consume
+			return (xy, extra))
+
+test_EvalStateI_Strict :: Suite
+test_EvalStateI_Strict = assertions "strict" $ do
+	$expect $ equal
+		((['a'], 'A'), ['b'])
+		(E.runLists_ [['a'], ['b']] $ do
+			xy <- ET.evalStateI' 'A' $ do
+				x <- EL.take 1
+				y <- lift StateT_S.get
+				lift (StateT_S.put 'B')
+				return (x, y)
+			extra <- EL.consume
+			return (xy, extra))
+
+test_RunWriterI :: Suite
+test_RunWriterI = suite "runWriterI"
+	[ test_RunWriterI_Lazy
+	, test_RunWriterI_Strict
+	]
+
+test_RunWriterI_Lazy :: Suite
+test_RunWriterI_Lazy = assertions "lazy" $ do
+	$expect $ equal
+		((['a'], ['A', 'B']), ['b'])
+		(E.runLists_ [['a'], ['b']] $ do
+			x <- ET.runWriterI $ do
+				lift (WriterT_L.tell ['A'])
+				x <- EL.take 1
+				lift (WriterT_L.tell ['B'])
+				return x
+			extra <- EL.consume
+			return (x, extra))
+	$expect $ equalExc
+		(ErrorCall "err")
+		(E.runLists [] $ ET.runWriterI $ do
+			_ <- E.throwError (ErrorCall "err")
+			lift (WriterT_L.tell ['A']))
+
+test_RunWriterI_Strict :: Suite
+test_RunWriterI_Strict = assertions "strict" $ do
+	$expect $ equal
+		((['a'], ['A', 'B']), ['b'])
+		(E.runLists_ [['a'], ['b']] $ do
+			x <- ET.runWriterI' $ do
+				lift (WriterT_S.tell ['A'])
+				x <- EL.take 1
+				lift (WriterT_S.tell ['B'])
+				return x
+			extra <- EL.consume
+			return (x, extra))
+	$expect $ equalExc
+		(ErrorCall "err")
+		(E.runLists [] $ ET.runWriterI' $ do
+			_ <- E.throwError (ErrorCall "err")
+			lift (WriterT_S.tell ['A']))
+
+test_ExecWriterI :: Suite
+test_ExecWriterI = suite "execWriterI"
+	[ test_ExecWriterI_Lazy
+	, test_ExecWriterI_Strict
+	]
+
+test_ExecWriterI_Lazy :: Suite
+test_ExecWriterI_Lazy = assertions "lazy" $ do
+	$expect $ equal
+		(['A', 'B'], ['b'])
+		(E.runLists_ [['a'], ['b']] $ do
+			x <- ET.execWriterI $ do
+				lift (WriterT_L.tell ['A'])
+				x <- EL.take 1
+				lift (WriterT_L.tell ['B'])
+				return x
+			extra <- EL.consume
+			return (x, extra))
+
+test_ExecWriterI_Strict :: Suite
+test_ExecWriterI_Strict = assertions "strict" $ do
+	$expect $ equal
+		(['A', 'B'], ['b'])
+		(E.runLists_ [['a'], ['b']] $ do
+			x <- ET.execWriterI' $ do
+				lift (WriterT_S.tell ['A'])
+				x <- EL.take 1
+				lift (WriterT_S.tell ['B'])
+				return x
+			extra <- EL.consume
+			return (x, extra))
+
+test_RunRWSI :: Suite
+test_RunRWSI = suite "runRWSI"
+	[ test_RunRWSI_Lazy
+	, test_RunRWSI_Strict
+	]
+
+test_RunRWSI_Lazy :: Suite
+test_RunRWSI_Lazy = assertions "lazy" $ do
+	$expect $ equal
+		(((['a'], 'A'), 'B', ['Y', 'Z']), ['b'])
+		(E.runLists_ [['a'], ['b']] $ do
+			xy <- ET.runRWSI 'A' 'A' $ do
+				lift (RWST_L.tell ['Y'])
+				x <- EL.take 1
+				y <- lift RWST_L.ask
+				lift (RWST_L.modify succ)
+				lift (RWST_L.tell ['Z'])
+				return (x, y)
+			extra <- EL.consume
+			return (xy, extra))
+	$expect $ equalExc
+		(ErrorCall "err")
+		(E.runLists [] $ ET.runRWSI 'A' 'A' $ do
+			_ <- E.throwError (ErrorCall "err")
+			lift (RWST_L.tell ['Y']))
+
+test_RunRWSI_Strict :: Suite
+test_RunRWSI_Strict = assertions "strict" $ do
+	$expect $ equal
+		(((['a'], 'A'), 'B', ['Y', 'Z']), ['b'])
+		(E.runLists_ [['a'], ['b']] $ do
+			xy <- ET.runRWSI' 'A' 'A' $ do
+				lift (RWST_S.tell ['Y'])
+				x <- EL.take 1
+				y <- lift RWST_S.ask
+				lift (RWST_S.modify succ)
+				lift (RWST_S.tell ['Z'])
+				return (x, y)
+			extra <- EL.consume
+			return (xy, extra))
+	$expect $ equalExc
+		(ErrorCall "err")
+		(E.runLists [] $ ET.runRWSI' 'A' 'A' $ do
+			_ <- E.throwError (ErrorCall "err")
+			lift (RWST_S.tell ['Y']))
+
+test_EvalRWSI :: Suite
+test_EvalRWSI = suite "evalRWSI"
+	[ test_EvalRWSI_Lazy
+	, test_EvalRWSI_Strict
+	]
+
+test_EvalRWSI_Lazy :: Suite
+test_EvalRWSI_Lazy = assertions "lazy" $ do
+	$expect $ equal
+		(((['a'], 'A'), ['Y', 'Z']), ['b'])
+		(E.runLists_ [['a'], ['b']] $ do
+			xy <- ET.evalRWSI 'A' 'Z' $ do
+				lift (RWST_L.tell ['Y'])
+				x <- EL.take 1
+				y <- lift RWST_L.ask
+				z <- lift RWST_L.get
+				lift (RWST_L.tell [z])
+				return (x, y)
+			extra <- EL.consume
+			return (xy, extra))
+
+test_EvalRWSI_Strict :: Suite
+test_EvalRWSI_Strict = assertions "strict" $ do
+	$expect $ equal
+		(((['a'], 'A'), ['Y', 'Z']), ['b'])
+		(E.runLists_ [['a'], ['b']] $ do
+			xy <- ET.evalRWSI' 'A' 'Z' $ do
+				lift (RWST_S.tell ['Y'])
+				x <- EL.take 1
+				y <- lift RWST_S.ask
+				z <- lift RWST_S.get
+				lift (RWST_S.tell [z])
+				return (x, y)
+			extra <- EL.consume
+			return (xy, extra))
+
+test_ExecRWSI :: Suite
+test_ExecRWSI = suite "execRWSI"
+	[ test_ExecRWSI_Lazy
+	, test_ExecRWSI_Strict
+	]
+
+test_ExecRWSI_Lazy :: Suite
+test_ExecRWSI_Lazy = assertions "lazy" $ do
+	$expect $ equal
+		(('B', ['Y', 'Z']), ['b'])
+		(E.runLists_ [['a'], ['b']] $ do
+			xy <- ET.execRWSI 'Z' 'A' $ do
+				lift (RWST_L.tell ['Y'])
+				x <- EL.take 1
+				y <- lift RWST_L.ask
+				lift (RWST_L.modify succ)
+				lift (RWST_L.tell [y])
+				return (x, y)
+			extra <- EL.consume
+			return (xy, extra))
+
+test_ExecRWSI_Strict :: Suite
+test_ExecRWSI_Strict = assertions "strict" $ do
+	$expect $ equal
+		(('B', ['Y', 'Z']), ['b'])
+		(E.runLists_ [['a'], ['b']] $ do
+			xy <- ET.execRWSI' 'Z' 'A' $ do
+				lift (RWST_S.tell ['Y'])
+				x <- EL.take 1
+				y <- lift RWST_S.ask
+				lift (RWST_S.modify succ)
+				lift (RWST_S.tell [y])
+				return (x, y)
+			extra <- EL.consume
+			return (xy, extra))
