diff --git a/quiver.cabal b/quiver.cabal
--- a/quiver.cabal
+++ b/quiver.cabal
@@ -1,5 +1,5 @@
 name:               quiver
-version:            1.1.1
+version:            1.1.2
 synopsis:           Quiver finite stream processing library
 homepage:           https://github.com/zadarnowski/quiver
 category:           Control
@@ -34,12 +34,12 @@
 source-repository this
   type:     git
   location: https://github.com/zadarnowski/quiver.git
-  tag:      1.1.1
+  tag:      1.1.2
 
 library
   hs-source-dirs:   src
   default-language: Haskell2010
-  ghc-options:      -O2 -Wall -fno-warn-unused-do-bind -fno-warn-missing-signatures
+  ghc-options:      -Wall -fno-warn-unused-do-bind -fno-warn-missing-signatures
   exposed-modules:  Control.Quiver
                     Control.Quiver.Internal
                     Control.Quiver.SP
diff --git a/src/Control/Quiver.lhs b/src/Control/Quiver.lhs
--- a/src/Control/Quiver.lhs
+++ b/src/Control/Quiver.lhs
@@ -20,7 +20,7 @@
 >   fetch, fetch_,
 >   emit, emit_,
 >   qlift, qhoist, qembed,
->   qpure, qid, qconcat,
+>   qpure, qid, qconcat, qtraverse,
 >   runEffect,
 >   (>>->), (>->>), (+>>->), (>>->+), (+>->>), (>->>+), (>&>),
 >   qcompose,
@@ -62,7 +62,7 @@
 
 > -- | @qpure g f z@ produces an infinite consumer/producer that
 > --   uses a pure function @f@ to convert every input value into
-> --   an output, and @f@ to convert each downstream response value
+> --   an output, and @g@ to convert each downstream response value
 > --   into an upstream request; the initial request is obtained
 > --   by applying @g@ to the initial response value @z@.
 
@@ -90,6 +90,18 @@
 >   cloop ys = consume ys (ploop []) (deliver ([], []))
 >   ploop ys (x:xs) = produce x (\y -> ploop (y:ys) xs) (deliver (xs, reverse ys))
 >   ploop ys [] = cloop (reverse ys)
+
+> -- | @qtraverse g f z@ produces an infinite consumer/producer that
+> --   uses a functor @f@ to convert every input value into
+> --   an output, and @g@ to convert each downstream response value
+> --   into an upstream request; the initial request is obtained
+> --   by applying @g@ to the initial response value @z@.
+
+> qtraverse :: Functor f => (b' -> f a) -> (a' -> f b) -> b' -> P a a' b b' f (Either a b)
+> qtraverse g f = cloop
+>  where
+>   cloop y = enclose (fmap (\y' -> consume y' ploop (deliver (Left y'))) (g y))
+>   ploop x = enclose (fmap (\x' -> produce x' cloop (deliver (Right x'))) (f x))
 
 > -- | Evaluates an /effect/, i.e., a processor that is both detached
 > --   and depleted and hence neither consumes nor produces any input,
diff --git a/src/Control/Quiver/SP.lhs b/src/Control/Quiver/SP.lhs
--- a/src/Control/Quiver/SP.lhs
+++ b/src/Control/Quiver/SP.lhs
@@ -33,6 +33,7 @@
 
 > import Control.Quiver
 > import Control.Quiver.Internal
+> import Data.Functor
 
 > infixr 5 >:>
 > infixl 1 >>?, >>!
@@ -223,19 +224,19 @@
 > -- | A processor that applies a monadic function to every input
 > --   element and emits the resulting value.
 
-> sptraverse :: Monad m => (a -> m b) -> SP a b m e
+> sptraverse :: Functor m => (a -> m b) -> SP a b m e
 > sptraverse k = loop
 >  where
 >   loop = spconsume loop' spcomplete
->   loop' x = qlift (k x) >>= (>:> loop)
+>   loop' x = enclose (fmap (>:> loop) (k x))
 
 > -- | A processor that consumes every input elemnet using a monadic function.
 
-> sptraverse_ :: Monad m => (a -> m ()) -> SConsumer a m e
+> sptraverse_ :: Functor m => (a -> m ()) -> SConsumer a m e
 > sptraverse_ k = loop
 >  where
 >   loop = spconsume loop' spcomplete
->   loop' x = qlift (k x) >> loop
+>   loop' x = enclose (k x $> loop)
 
 > -- | Produces every element of a foldable structure.
 
