diff --git a/pipe-enumerator.cabal b/pipe-enumerator.cabal
--- a/pipe-enumerator.cabal
+++ b/pipe-enumerator.cabal
@@ -1,5 +1,5 @@
 name:           pipe-enumerator
-version:        0.2.0.0
+version:        0.3.0.0
 synopsis:       A bidirectional bridge between pipes and iteratees
 homepage:       https://github.com/zadarnowski/pipe-enumerator
 category:       Control, Pipes
@@ -34,7 +34,7 @@
 source-repository this
   type:         git
   location:     https://github.com/zadarnowski/pipe-enumerator.git
-  tag:          0.2.0.0
+  tag:          0.3.0.0
 
 library
   hs-source-dirs:   src
diff --git a/src/Pipes/Enumerator.lhs b/src/Pipes/Enumerator.lhs
--- a/src/Pipes/Enumerator.lhs
+++ b/src/Pipes/Enumerator.lhs
@@ -100,72 +100,71 @@
 >   convert5 (P.Pure r)             = E.yield r E.EOF
 
 > -- | Feed the output of a 'P.Pipe' to a 'E.Step', effectively converting it into
-> --   an 'E.Enumerator',  generalised slightly to allow distinct input and output
-> --   types.  The chunks of the input stream are fed into the pipe one element at
-> --   the time, and the pipe's  output is fed to the iteratee one element per chunk.
+> --   an 'E.Enumerator', generalised slightly to allow distinct input and output
+> --   types. The chunks of the input stream are fed into the pipe one element at
+> --   the time, and the pipe's output is fed to the iteratee one element per chunk.
 > --   Once the input reaches 'E.EOF', the pipe is fed an infinite stream of 'Nothing'
-> --   until it ends with  a pure value. In effect, both the pipe and the iteratee are
-> --   always consumed fully, with the resulting enumerator returning the results of both.
-> pipeToEnumerator :: Monad m => P.Proxy a' (Maybe a) () b m q -> E.Step b m r -> E.Iteratee a m (q, r)
-> pipeToEnumerator = advanceIteratee []
+> --   until it ends with  a pure value, which is discarded. In effect, both the pipe
+> --   and the iteratee are always consumed fully.
+> pipeToEnumerator :: Monad m => P.Proxy a' (Maybe a) () b m r' -> E.Step b m r -> E.Iteratee a m r
+> pipeToEnumerator = pipeToEnumerator' (curry (return . snd))
+
+> -- | Feed the output of a 'P.Pipe' to a 'E.Step', effectively converting it into
+> --   an 'E.Enumerator', generalised to allow distinct input and output types
+> --   and a custom monadic function for merging of the pipe's and step's results
+> --   into a single result of the constructed iteratee. The chunks of the input
+> --   stream are fed into the pipe one element at the time, and the pipe's output
+> --   is fed to the iteratee one element per chunk.  Once the input reaches 'E.EOF',
+> --   the pipe is fed an infinite stream of 'Nothing' until it ends with  a pure value,
+> --   which is combined with the step's result using the supplied monadic function @f@.
+> --   In effect, both the pipe and the iteratee are always consumed fully, with the
+> --   resulting iteratee returning the results of both transformers.
+> pipeToEnumerator' :: Monad m => (r1 -> r2 -> m r) -> P.Proxy a' (Maybe a) () b m r1 -> E.Step b m r2 -> E.Iteratee a m r
+> pipeToEnumerator' f = advanceIteratee []
 >  where
 
->   advanceIteratee :: Monad m => [a] -> P.Proxy a' (Maybe a) () b m q -> E.Step b m r -> E.Iteratee a m (q, r)
 >   advanceIteratee cs p (E.Continue ik)      = advancePipe cs ik p
 >   advanceIteratee cs p s                    = drainPipe cs s p
 
->   advanceIteratee' :: Monad m => P.Proxy a' (Maybe a) () b m q -> E.Step b m r -> E.Iteratee a m (q, r)
 >   advanceIteratee' p (E.Continue ik)        = advancePipe' ik p
 >   advanceIteratee' p s                      = drainPipe' s p
 
->   advancePipe :: Monad m => [a] -> (E.Stream b -> E.Iteratee b m r) -> P.Proxy a' (Maybe a) () b m q -> E.Iteratee a m (q, r)
 >   advancePipe cs ik (P.Request _ pk)        = advancePipeWithChunks ik pk cs
 >   advancePipe cs ik (P.Respond x pk)        = ik (E.Chunks [x]) E.>>== advanceIteratee cs (pk ())
 >   advancePipe cs ik (P.M m)                 = lift m >>= advancePipe cs ik
->   advancePipe cs ik (P.Pure q)              = ik (E.EOF) E.>>== finish q (E.Chunks cs)
+>   advancePipe cs ik (P.Pure r1)             = ik (E.EOF) E.>>== finish r1 (E.Chunks cs)
 
->   advancePipe' :: Monad m => (E.Stream b -> E.Iteratee b m r) -> P.Proxy a' (Maybe a) () b m q -> E.Iteratee a m (q, r)
 >   advancePipe' ik (P.Request _ pk)          = advancePipeWithEOF ik pk
 >   advancePipe' ik (P.Respond x pk)          = ik (E.Chunks [x]) E.>>== advanceIteratee' (pk ())
 >   advancePipe' ik (P.M m)                   = lift m >>= advancePipe' ik
->   advancePipe' ik (P.Pure q)                = ik (E.EOF) E.>>== finish q (E.EOF)
+>   advancePipe' ik (P.Pure r1)               = ik (E.EOF) E.>>== finish r1 (E.EOF)
 
->   advancePipeWithStream :: Monad m => (E.Stream b -> E.Iteratee b m r) -> (Maybe a -> P.Proxy a' (Maybe a) () b m q) -> E.Stream a -> E.Iteratee a m (q, r)
 >   advancePipeWithStream ik pk (E.Chunks cs) = advancePipeWithChunks ik pk cs
 >   advancePipeWithStream ik pk (E.EOF)       = advancePipeWithEOF ik pk
 
->   advancePipeWithChunks :: Monad m => (E.Stream b -> E.Iteratee b m r) -> (Maybe a -> P.Proxy a' (Maybe a) () b m q) -> [a] -> E.Iteratee a m (q, r)
 >   advancePipeWithChunks ik pk (c:cs)        = advancePipe cs ik (pk (Just c))
 >   advancePipeWithChunks ik pk []            = E.continue (advancePipeWithStream ik pk)
 
->   advancePipeWithEOF :: Monad m => (E.Stream b -> E.Iteratee b m r) -> (Maybe a -> P.Proxy a' (Maybe a) () b m q) -> E.Iteratee a m (q, r)
 >   advancePipeWithEOF ik pk                  = advancePipe' ik (pk Nothing)
 
->   drainPipe :: Monad m => [a] -> E.Step b m r -> P.Proxy a' (Maybe a) () b m q -> E.Iteratee a m (q, r)
 >   drainPipe cs s (P.Request _ pk)           = drainPipeWithChunks s pk cs
 >   drainPipe cs s (P.Respond _ pk)           = drainPipe cs s (pk ())
 >   drainPipe cs s (P.M m)                    = lift m >>= drainPipe cs s
->   drainPipe cs s (P.Pure q)                 = finish q (E.Chunks cs) s
+>   drainPipe cs s (P.Pure r1)                = finish r1 (E.Chunks cs) s
 
->   drainPipe' :: Monad m => E.Step b m r -> P.Proxy a' (Maybe a) () b m q -> E.Iteratee a m (q, r)
 >   drainPipe' s (P.Request _ pk)             = drainPipeWithEOF s pk
 >   drainPipe' s (P.Respond _ pk)             = drainPipe' s (pk ())
 >   drainPipe' s (P.M m)                      = lift m >>= drainPipe' s
->   drainPipe' s (P.Pure q)                   = finish q (E.EOF) s
+>   drainPipe' s (P.Pure r1)                  = finish r1 (E.EOF) s
 
->   drainPipeWithStream :: Monad m => E.Step b m r -> (Maybe a -> P.Proxy a' (Maybe a) () b m q) -> E.Stream a -> E.Iteratee a m (q, r)
 >   drainPipeWithStream s pk (E.Chunks cs)    = drainPipeWithChunks s pk cs
 >   drainPipeWithStream s pk (E.EOF)          = drainPipeWithEOF s pk
 
->   drainPipeWithChunks :: Monad m => E.Step b m r -> (Maybe a -> P.Proxy a' (Maybe a) () b m q) -> [a] -> E.Iteratee a m (q, r)
 >   drainPipeWithChunks s pk (c:cs)           = drainPipe cs s (pk (Just c))
 >   drainPipeWithChunks s pk []               = E.continue (drainPipeWithStream s pk)
 
->   drainPipeWithEOF :: Monad m => E.Step b m r -> (Maybe a -> P.Proxy a' (Maybe a) () b m q) -> E.Iteratee a m (q, r)
 >   drainPipeWithEOF s pk                     = drainPipe' s (pk Nothing)
 
->   finish :: Monad m => q -> E.Stream a -> E.Step b m r -> E.Iteratee a m (q, r)
->   finish q xs (E.Yield r _)                 = E.yield (q, r) xs
->   finish _ _  (E.Error e)                   = E.throwError e
->   finish _ _  (E.Continue _)                = error "divergent iteratee" -- iteratees aren't allowed to continue on EOF
-
+>   finish r1 xs (E.Yield r2 _)                = lift (f r1 r2) >>= flip E.yield xs
+>   finish _  _  (E.Error e)                   = E.throwError e
+>   finish _  _  (E.Continue _)                = error "divergent iteratee" -- iteratees aren't allowed to continue on EOF
