diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,34 @@
+Quiver
+======
+
+    Copyright © 2015 Patryk Zadarnowski «pat@jantar.org».
+    All rights reserved.
+
+_Quiver_ is a powerful stream processing library for
+combinatorial and monadic representation of computations
+over both inductive and coinductive data streams.
+
+It is similar to Gabriel Gonzalez's _pipes_ and
+Michael Snoyman's _conduit_, but generalises both
+with support for functor-based computations and
+a clean support for finite (i.e., inductive) data
+streams, both upstream and downstream of the computation
+being defined.
+
+The underlying data structure, `P`, is almost identical
+to the `Proxy` data structure of the `Pipes` library,
+except that the `Consume` and `Produce` constructors
+(corresponding, respectively, to `Request` and `Response`
+in the Pipes' `Proxy` data type) include an additional
+argument which explicitly captures the processor's
+behaviour in the event of input stream depletion
+(for `Consume`) or output decoupling (for `Produce`).
+This simple mechanism subsumes Conduit's need for
+elaborate unconsumed-input tracking mechanisms,
+and allows us to provide a mathematically-clean
+framework for processing of finite data streams.
+
+This library is currently very young, and users should
+expect significant changes to the Quiver core combinators
+as the underlying theory is developed and the interface
+stabilises asymptotically to the future version 1.0.
diff --git a/quiver.cabal b/quiver.cabal
--- a/quiver.cabal
+++ b/quiver.cabal
@@ -1,51 +1,49 @@
-name:           quiver
-version:        0.0.0.12
-synopsis:       Quiver finite stream processing library
-homepage:       https://github.com/zadarnowski/quiver
-category:       Control
-stability:      alpha
-
-author:         Patryk Zadarnowski
-maintainer:     Patryk Zadarnowski <pat@jantar.org>
+name:               quiver
+version:            1.0.0
+synopsis:           Quiver finite stream processing library
+homepage:           https://github.com/zadarnowski/quiver
+category:           Control
+stability:          alpha
 
-copyright:      Copyright (c) 2015 Patryk Zadarnowski
+author:             Patryk Zadarnowski
+maintainer:         Patryk Zadarnowski <pat@jantar.org>
 
-description:
+copyright:          Copyright (c) 2015 Patryk Zadarnowski
 
-    /Quiver/ is a powerful stream processing library for
-    combinatorial and monadic representation of computations
-    over both inductive and coinductive data streams.
-    .
-    It is similar to Gabriel Gonzalez's /pipes/ and
-    Michael Snoyman's /conduit/, but generalises both
-    with support for functor-based computations and
-    a clean support for finite (i.e., inductive) data
-    streams, both upstream and downstream of the computation
-    being defined.
+description:        /Quiver/ is a powerful stream processing library for
+                    combinatorial and monadic representation of computations
+                    over both inductive and coinductive data streams.
+                    .
+                    It is similar to Gabriel Gonzalez's /pipes/ and
+                    Michael Snoyman's /conduit/, but generalises both
+                    with support for functor-based computations and
+                    a clean support for finite (i.e., inductive) data
+                    streams, both upstream and downstream of the computation
+                    being defined.
 
-cabal-version:  >= 1.18
-build-type:     Simple
-license:        BSD3
-license-file:   LICENSE
+cabal-version:      >= 1.18
+build-type:         Simple
+license:            BSD3
+license-file:       LICENSE
+extra-source-files: README.md
 
 source-repository head
-  type:         git
-  location:     https://github.com/zadarnowski/quiver.git
+  type:     git
+  location: https://github.com/zadarnowski/quiver.git
 
 source-repository this
-  type:         git
-  location:     https://github.com/zadarnowski/quiver.git
-  tag:          0.0.0.12
+  type:     git
+  location: https://github.com/zadarnowski/quiver.git
+  tag:      1.0.0
 
 library
   hs-source-dirs:   src
   default-language: Haskell2010
   ghc-options:      -O2 -Wall -fno-warn-unused-do-bind -fno-warn-missing-signatures
-
-  exposed-modules:
-    Control.Quiver
-    Control.Quiver.Internal
-    Control.Quiver.SP
-
-  build-depends:
-    base >= 4.8 && < 5
+  exposed-modules:  Control.Quiver
+                    Control.Quiver.Internal
+                    Control.Quiver.SP
+                    Control.Quiver.Trans
+  build-depends:    base >= 4.8 && < 5,
+                    mmorph >= 1.0.4,
+                    transformers >= 0.4.3.0
diff --git a/src/Control/Quiver.lhs b/src/Control/Quiver.lhs
--- a/src/Control/Quiver.lhs
+++ b/src/Control/Quiver.lhs
@@ -19,7 +19,7 @@
 >   -- Defined below:
 >   fetch, fetch_,
 >   emit, emit_,
->   qlift,
+>   qlift, qhoist,
 >   qpure, qid, qconcat,
 >   runEffect,
 >   (>>->), (>->>), (>&>),
@@ -28,7 +28,7 @@
 
 > import Control.Quiver.Internal
 
-> infixl 0 >>->, >->>, >&>
+> infixl 1 >>->, >->>, >&>
 
 > -- | @fetch x@ represents a singleton stream processor that
 > --   sends the request value @x@ upstream and delivers the
@@ -59,11 +59,6 @@
 
 > emit_ :: b -> P a a' b b' f ()
 > emit_ y = produce y (deliver . const ()) (deliver ())
-
-> -- | @qlift@ lifts the value of a base functor into a stream processor.
-
-> qlift :: Functor f => f r -> P a a' b b' f r
-> qlift = enclose . fmap deliver
 
 > -- | @qpure g f z@ produces an infinite consumer/producer that
 > --   uses a pure function @f@ to convert every input value into
diff --git a/src/Control/Quiver/Internal.lhs b/src/Control/Quiver/Internal.lhs
--- a/src/Control/Quiver/Internal.lhs
+++ b/src/Control/Quiver/Internal.lhs
@@ -31,9 +31,13 @@
 >   P (..), Producer, Consumer, Effect,
 >   consume, produce, enclose, deliver,
 >   decouple, deplete,
+>   qlift, qhoist, qembed
 > ) where
 
+> import Control.Monad.IO.Class
+> import Control.Monad.Morph
 
+
   Data Types
   ==========
 
@@ -143,8 +147,21 @@
 >   (Produce y k q) >>= kk = Produce y ((>>= kk) . k) (q >>= deplete . kk)
 >   (Enclose f)     >>= kk = Enclose (fmap (>>= kk) f)
 >   (Deliver r)     >>= kk = kk r
+>   fail                   = Enclose . fail
 
+> instance MonadTrans (P a a' b b') where
+>   lift = qlift
 
+> instance MonadIO f => MonadIO (P a a' b b' f) where
+>   liftIO = lift . liftIO
+
+> instance MFunctor (P a a' b b') where
+>   hoist = qhoist
+
+> instance MMonad (P a a' b b') where
+>   embed = qembed
+
+
   Primitive Combinators
   =====================
 
@@ -206,3 +223,37 @@
 > deplete (Enclose f) = Enclose (fmap deplete f)
 > deplete (Deliver r) = Deliver r
 
+
+  Generalized Transformers
+  ========================
+
+> -- | @qlift@ lifts the value of a base functor into a stream processor;
+> --   same as 'lift' from 'MonadTrans', but relaxing constraint on
+> --   the base structure from 'Monad' to 'Functor'.
+
+> qlift :: Functor f => f r -> P a a' b b' f r
+> qlift = enclose . fmap deliver
+
+> -- | @qhoist@ morphs the value of a base functor into another
+> --   functor by applying the supplied functor morphism to every
+> --   'Enclose' step of a stream processor; same as 'hoist' from
+> --   'MFunctor' but relaxing the constraint on the base structure
+> --   from 'Monad' to 'Functor'.
+
+> qhoist :: Functor f => (forall x . f x -> g x) -> P a a' b b' f r -> P a a' b b' g r
+> qhoist ff = loop
+>  where
+>   loop (Consume x k q) = consume x (loop . k) (qhoist ff q)
+>   loop (Produce y k q) = produce y (loop . k) (qhoist ff q)
+>   loop (Enclose f)     = enclose (ff (fmap loop f))
+>   loop (Deliver r)     = deliver r
+
+> -- | @qembed@ ...
+
+> qembed :: Monad g => (forall x . f x -> P a a' b b' g x) -> P a a' b b' f r -> P a a' b b' g r
+> qembed ff = loop
+>  where
+>   loop (Consume x k q) = consume x (loop . k) (decouple $ qembed ff q)
+>   loop (Produce y k q) = produce y (loop . k) (deplete $ qembed ff q)
+>   loop (Enclose f)     = ff f >>= loop
+>   loop (Deliver r)     = deliver r
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
@@ -15,11 +15,12 @@
 
 > module Control.Quiver.SP (
 >   module Control.Quiver,
->   SQ, SP, SPResult,
+>   SQ, SP, SProducer, SConsumer, SEffect, SPResult,
 >   pattern SPComplete,
 >   pattern SPFailed,
 >   pattern SPIncomplete,
->   spfetch, spemit, (>:>), (>>!),
+>   spcomplete, spfailed, spincomplete,
+>   spfetch, spemit, (>:>), (>>?), (>>!),
 >   sppure, spid, spconcat,
 >   spfold, spfold', spfoldl, spfoldl', spfoldr, spfoldr',
 >   sptraverse, sptraverse_,
@@ -28,7 +29,7 @@
 > import Control.Quiver
 
 > infixr 5 >:>
-> infixl 1 >>!
+> infixl 1 >>?, >>!
 
 > -- | A /simple processor step/ with a unit request type and an unspecified
 > --   response type:
@@ -42,22 +43,49 @@
 
 > type SP a b f e = SQ a b f (SPResult e)
 
+> -- | A producer version of a simple processor.
+
+> type SProducer b f e = forall a . SP a b f e
+
+> -- | A consumer version of a simple processor.
+
+> type SConsumer a f e = forall b . SP a b f e
+
+> -- | An effect version of a simple processor.
+
+> type SEffect f e = forall a b . SP a b f e
+
 > -- | Simple processor result type.
 
 > type SPResult e = Maybe (Maybe e)
 
-> -- | Simple processor result value indicating successful processing of the entire input stream.
+> -- | ('Just Nothing') Simple processor result value indicating successful processing of the entire input stream.
 
 > pattern SPComplete = Just Nothing
 
-> -- | Simple processor result value indicating unsuccessful processing of the input stream.
+> -- | ('Just (Just e)') Simple processor result value indicating unsuccessful processing of the input stream.
 
 > pattern SPFailed e = Just (Just e)
 
-> -- | Simple processor result value indicating premature termination of the consumer.
+> -- | ('Nothing') Simple processor result value indicating premature termination of the consumer.
 
 > pattern SPIncomplete = Nothing
 
+> -- | Delivers an 'SPComplete' result.
+
+> spcomplete :: P a a' b b' f (SPResult e)
+> spcomplete = deliver SPComplete
+
+> -- | Delivers an 'SPFailed' result.
+
+> spfailed :: e -> P a a' b b' f (SPResult e)
+> spfailed = deliver . SPFailed
+
+> -- | Delivers an 'SPIncomplete' result.
+
+> spincomplete :: P a a' b b' f (SPResult e)
+> spincomplete = deliver SPIncomplete
+
 > -- | @spfetch@ represents a singleton simple stream processor that
 > --   sends the request value @x@ upstream and delivers the
 > --   next input value received, or @Nothing@ if the upstream
@@ -72,7 +100,7 @@
 > --   or 'SPIncomplete' otherwise.
 
 > spemit :: b -> P a a' b b' f (SPResult e)
-> spemit y = produce y (const $ deliver SPComplete) (deliver SPIncomplete)
+> spemit y = produce y (const spcomplete) spincomplete
 
 > -- | @y >:> p@ represents a singleton stream processor that
 > --   produces a single output value @y@ and continues with
@@ -80,16 +108,24 @@
 > --   not be consumed by the downstream processor.
 
 > (>:>) :: b -> P a a' b b' f (SPResult e) -> P a a' b b' f (SPResult e)
-> y >:> p = produce y (const p) (deliver SPIncomplete)
+> y >:> p = produce y (const p) spincomplete
 
+> -- | @p >>? q@ continues processing of @p@ with @q@ but only
+> --   if @p@ completes successsfully by delivering 'SPComplete',
+> --   short-circuiting @q@ if @p@ fails with 'SPIncomplete' or
+> --   'SPFailed'.
+
+> (>>?) :: Monad f => P a a' b b' f (SPResult e) -> P a a' b b' f (SPResult e) -> P a a' b b' f (SPResult e)
+> p >>? q = p >>= maybe spincomplete (maybe q spfailed)
+
 > -- | @p >>! k@ is equivalent to @p@, with any failures in @p@
 > --   supplied to the continuation processor @k@. Note that
 > --   @k@ is not executed if @p@ completes successfully with
 > --   'SPComplete' or is interrupted by the downstream processor,
-> --   deliverying 'SPIncomplete'.
+> --   delivering 'SPIncomplete'.
 
 > (>>!) :: Monad f => P a a' b b' f (SPResult e) -> (e -> P a a' b b' f (SPResult e')) -> P a a' b b' f (SPResult e')
-> p >>! k = p >>= maybe (deliver SPIncomplete) (maybe (deliver SPComplete) k)
+> p >>! k = p >>= maybe spincomplete (maybe spcomplete k)
 
 > -- | @sppure f@ produces an infinite consumer/producer that
 > --   uses a pure function @f@ to convert every input value into
@@ -98,24 +134,24 @@
 > sppure :: (a -> b) -> SP a b f e
 > sppure f = cloop
 >  where
->   cloop = consume () ploop (deliver SPComplete)
->   ploop x = produce (f x) (const cloop) (deliver SPIncomplete)
+>   cloop = consume () ploop spcomplete
+>   ploop x = produce (f x) (const cloop) spincomplete
 
 > -- | A simple identity processor, equivalent to 'sppure id'.
 
 > spid :: SP a a f e
 > spid = cloop
 >  where
->   cloop = consume () ploop (deliver SPComplete)
->   ploop x = produce x (const cloop) (deliver SPIncomplete)
+>   cloop = consume () ploop spcomplete
+>   ploop x = produce x (const cloop) spincomplete
 
 > -- | A simple list flattening processor requests.
 
 > spconcat :: SP [a] a f e
 > spconcat = cloop
 >  where
->   cloop = consume () ploop (deliver SPComplete)
->   ploop (x:xs) = produce x (const $ ploop xs) (deliver SPIncomplete)
+>   cloop = consume () ploop spcomplete
+>   ploop (x:xs) = produce x (const $ ploop xs) spincomplete
 >   ploop [] = cloop
 
 > -- | A processor that delivers the entire input of the stream folded
@@ -176,7 +212,7 @@
 > sptraverse :: Monad m => (a -> m b) -> SP a b m e
 > sptraverse k = loop
 >  where
->   loop = consume () loop' (deliver SPComplete)
+>   loop = consume () loop' spcomplete
 >   loop' x = qlift (k x) >>= (>:> loop)
 
 > -- | A processor that consumes every input elemnet using a monadic function.
@@ -184,5 +220,5 @@
 > sptraverse_ :: Monad m => (a -> m ()) -> SP a b m e
 > sptraverse_ k = loop
 >  where
->   loop = consume () loop' (deliver SPComplete)
+>   loop = consume () loop' spcomplete
 >   loop' x = qlift (k x) >> loop
diff --git a/src/Control/Quiver/Trans.lhs b/src/Control/Quiver/Trans.lhs
new file mode 100644
--- /dev/null
+++ b/src/Control/Quiver/Trans.lhs
@@ -0,0 +1,163 @@
+> -- | Module:    Control.Quiver.Trans
+> -- Description: Monad transformers for quiver processors
+> -- Copyright:   © 2015 Patryk Zadarnowski <pat@jantar.org>
+> -- License:     BSD3
+> -- Maintainer:  pat@jantar.org
+> -- Stability:   experimental
+> -- Portability: portable
+> --
+> -- This module provides functions for hoisting stream processors
+> -- over the various well-known monad transformers into the corresponding
+> -- base monad, in a manner analogous to the tranformers' @run@ function.
+> --
+> -- This is particularly useful for composing quiver processors over
+> -- distinct “compatible” monads such as 'ReaderT' and 'StateT'.
+
+> {-# LANGUAGE RankNTypes #-}
+> {-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}
+
+> module Control.Quiver.Trans (
+>   qRunErrorT,
+>   qRunExceptT,
+>   qRunMaybeT,
+>   qRunRWST, qRunLazyRWST, qRunStrictRWST,
+>   qRunReaderT,
+>   qRunStateT, qRunLazyStateT, qRunStrictStateT,
+>   qRunWriterT, qRunLazyWriterT, qRunStrictWriterT,
+> ) where
+
+> import Control.Monad.Trans.Error
+> import Control.Monad.Trans.Except
+> import Control.Monad.Trans.Maybe
+> import Control.Monad.Trans.RWS.Lazy as Lazy
+> import Control.Monad.Trans.RWS.Strict as Strict
+> import Control.Monad.Trans.Reader
+> import Control.Monad.Trans.State.Lazy as Lazy
+> import Control.Monad.Trans.State.Strict as Strict
+> import Control.Monad.Trans.Writer.Lazy as Lazy
+> import Control.Monad.Trans.Writer.Strict as Strict
+> import Control.Quiver.Internal
+
+> -- | Hoists a stream processor from an 'ErrorT e m' monad into its base monad @m@.
+
+> qRunErrorT :: Functor m => P a a' b b' (ErrorT e m) r -> P a a' b b' m (Either e r)
+> qRunErrorT = loop
+>  where
+>   loop (Consume x k q) = consume x (loop . k) (qRunErrorT q)
+>   loop (Produce y k q) = produce y (loop . k) (qRunErrorT q)
+>   loop (Enclose f)     = enclose (either (deliver . Left) loop <$> runErrorT f)
+>   loop (Deliver r)     = deliver (Right r)
+
+> -- | Hoists a stream processor from an 'ExceptT e m' monad into its base monad @m@.
+
+> qRunExceptT :: Functor m => P a a' b b' (ExceptT e m) r -> P a a' b b' m (Either e r)
+> qRunExceptT = loop
+>  where
+>   loop (Consume x k q) = consume x (loop . k) (qRunExceptT q)
+>   loop (Produce y k q) = produce y (loop . k) (qRunExceptT q)
+>   loop (Enclose f)     = enclose (either (deliver . Left) loop <$> runExceptT f)
+>   loop (Deliver r)     = deliver (Right r)
+
+> -- | Hoists a stream processor from a 'MaybeT m' monad into its base monad @m@.
+
+> qRunMaybeT :: Functor m => P a a' b b' (MaybeT m) r -> P a a' b b' m (Maybe r)
+> qRunMaybeT = loop
+>  where
+>   loop (Consume x k q) = consume x (loop . k) (qRunMaybeT q)
+>   loop (Produce y k q) = produce y (loop . k) (qRunMaybeT q)
+>   loop (Enclose f)     = enclose (maybe (deliver Nothing) loop <$> runMaybeT f)
+>   loop (Deliver r)     = deliver (Just r)
+
+> -- | Hoists a stream processor from a lazy 'RWST r w s m' monad into its base monad @m@.
+
+> qRunRWST :: (Functor m, Monoid mw) => P a a' b b' (Lazy.RWST mr mw ms m) r -> mr -> ms -> P a a' b b' m (r, ms, mw)
+> qRunRWST = qRunLazyRWST
+
+> -- | Hoists a stream processor from a lazy 'RWST r w s m' monad into its base monad @m@.
+
+> qRunLazyRWST :: (Functor m, Monoid mw) => P a a' b b' (Lazy.RWST mr mw ms m) r -> mr -> ms -> P a a' b b' m (r, ms, mw)
+> qRunLazyRWST p mr ms = loop p
+>  where
+>   loop (Consume x k q) = consume x (loop . k) (qRunLazyRWST q mr ms)
+>   loop (Produce y k q) = produce y (loop . k) (qRunLazyRWST q mr ms)
+>   loop (Enclose f)     = enclose (run <$> Lazy.runRWST f mr ms)
+>   loop (Deliver r)     = deliver (r, ms, mempty)
+>   run ~(p', ms', mw)    = adj mw <$> qRunLazyRWST p' mr ms'
+>   adj mw ~(r, ms', mw') = (r, ms', mappend mw mw')
+
+> -- | Hoists a stream processor from a strict 'RWST r w s m' monad into its base monad @m@.
+
+> qRunStrictRWST :: (Functor m, Monoid mw) => P a a' b b' (Strict.RWST mr mw ms m) r -> mr -> ms -> P a a' b b' m (r, ms, mw)
+> qRunStrictRWST p mr ms = loop p
+>  where
+>   loop (Consume x k q) = consume x (loop . k) (qRunStrictRWST q mr ms)
+>   loop (Produce y k q) = produce y (loop . k) (qRunStrictRWST q mr ms)
+>   loop (Enclose f)     = enclose (run <$> Strict.runRWST f mr ms)
+>   loop (Deliver r)     = deliver (r, ms, mempty)
+>   run (p', ms', mw)    = adj mw <$> qRunStrictRWST p' mr ms'
+>   adj mw (r, ms', mw') = (r, ms', mappend mw mw')
+
+> -- | Hoists a stream processor from a 'ReaderT r m' monad into its base monad @m@.
+
+> qRunReaderT :: Functor m => P a a' b b' (ReaderT mr m) r -> mr -> P a a' b b' m r
+> qRunReaderT p mr = loop p
+>  where
+>   loop (Consume x k q) = consume x (loop . k) (qRunReaderT q mr)
+>   loop (Produce y k q) = produce y (loop . k) (qRunReaderT q mr)
+>   loop (Enclose f)     = enclose (loop <$> runReaderT f mr)
+>   loop (Deliver r)     = deliver r
+
+> -- | Hoists a stream processor from a lazy 'StateT s m' monad into its base monad @m@.
+
+> qRunStateT :: Functor m => P a a' b b' (Lazy.StateT ms m) r -> ms -> P a a' b b' m (r, ms)
+> qRunStateT = qRunLazyStateT
+
+> -- | Hoists a stream processor from a lazy 'StateT s m' monad into its base monad @m@.
+
+> qRunLazyStateT :: Functor m => P a a' b b' (Lazy.StateT ms m) r -> ms -> P a a' b b' m (r, ms)
+> qRunLazyStateT p ms = loop p
+>  where
+>   loop (Consume x k q) = consume x (loop . k) (qRunLazyStateT q ms)
+>   loop (Produce y k q) = produce y (loop . k) (qRunLazyStateT q ms)
+>   loop (Enclose f)     = enclose (run <$> Lazy.runStateT f ms)
+>   loop (Deliver r)     = deliver (r, ms)
+>   run ~(p', ms')       = qRunLazyStateT p' ms'
+
+> -- | Hoists a stream processor from a strict 'StateT s m' monad into its base monad @m@.
+
+> qRunStrictStateT :: Functor m => P a a' b b' (Strict.StateT ms m) r -> ms -> P a a' b b' m (r, ms)
+> qRunStrictStateT p ms = loop p
+>  where
+>   loop (Consume x k q) = consume x (loop . k) (qRunStrictStateT q ms)
+>   loop (Produce y k q) = produce y (loop . k) (qRunStrictStateT q ms)
+>   loop (Enclose f)     = enclose (uncurry qRunStrictStateT <$> Strict.runStateT f ms)
+>   loop (Deliver r)     = deliver (r, ms)
+
+> -- | Hoists a stream processor from a lazy 'WriterT w m' monad into its base monad @m@.
+
+> qRunWriterT :: (Functor m, Monoid mw) => P a a' b b' (Lazy.WriterT mw m) r -> P a a' b b' m (r, mw)
+> qRunWriterT = qRunLazyWriterT
+
+> -- | Hoists a stream processor from a lazy 'WriterT w m' monad into its base monad @m@.
+
+> qRunLazyWriterT :: (Functor m, Monoid mw) => P a a' b b' (Lazy.WriterT mw m) r -> P a a' b b' m (r, mw)
+> qRunLazyWriterT p = loop p
+>  where
+>   loop (Consume x k q) = consume x (loop . k) (qRunLazyWriterT q)
+>   loop (Produce y k q) = produce y (loop . k) (qRunLazyWriterT q)
+>   loop (Enclose f)     = enclose (run <$> Lazy.runWriterT f)
+>   loop (Deliver r)     = deliver (r, mempty)
+>   run ~(p', mw)        = adj mw <$> qRunLazyWriterT p'
+>   adj mw ~(r, mw')     = (r, mappend mw mw')
+
+> -- | Hoists a stream processor from a strict 'WriterT w m' monad into its base monad @m@.
+
+> qRunStrictWriterT :: (Functor m, Monoid mw) => P a a' b b' (Strict.WriterT mw m) r -> P a a' b b' m (r, mw)
+> qRunStrictWriterT p = loop p
+>  where
+>   loop (Consume x k q) = consume x (loop . k) (qRunStrictWriterT q)
+>   loop (Produce y k q) = produce y (loop . k) (qRunStrictWriterT q)
+>   loop (Enclose f)     = enclose (run <$> Strict.runWriterT f)
+>   loop (Deliver r)     = deliver (r, mempty)
+>   run (p', mw)         = adj mw <$> qRunStrictWriterT p'
+>   adj mw (r, mw')      = (r, mappend mw mw')
