diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,173 @@
+4.3.16
+
+* Fix example code for `every`
+* Improved documentation for `ListT`
+
+4.3.15
+
+* Build against `ghc-9.0`
+
+4.3.14
+
+* Add `mapMaybe` and `wither`, and more laws for `filter` and `filterM`.
+
+4.3.13
+
+* Add `MonadFail` instance for `Proxy`
+
+4.3.12
+
+* Fix space leak introduced in version 4.3.10
+    * This leak primarily affects the use of `forever`
+
+4.3.11
+
+* Fix documentation for `scanM`
+
+4.3.10
+
+* Relax `Monad` constraints to `Functor`
+* Support GHC 8.8
+
+4.3.9
+
+* Increase upper bound on `exceptions`
+
+4.3.8
+
+* Increase upper bound on `exceptions`
+
+4.3.7
+
+* Documentation fix
+
+4.3.6
+
+* Fix implementation of `pass` in `MonadWriter` instance for `Proxy`
+
+4.3.5
+
+* Support `Semigroup` being a super-class of `Monoid`
+
+4.3.4
+
+* Increase upper bound on `mmorph`
+
+4.3.3
+
+* Make `X` a synonym for `Data.Void.Void`
+
+4.3.2
+
+* BUG FIX: Fix `MMonad` instance for `ListT`
+    * The old instance was an infinite loop
+
+4.3.1
+
+* Support building against `ghc-7.4`
+
+4.3.0
+
+* BREAKING CHANGE: Remove `Alternative`/`MonadPlus` instances for `Proxy`
+    * See commit 08e7302f43dbf2a40bd367c5ee73ee3367e17768 which explains why
+* Add `Traversable` instance for `ListT`
+* New `MonadThrow`/`MonadCatch`/`MMonad`/`Semigroup`/`MonadZip` instances for
+  `ListT`
+* New `MonadThrow`/`MonadCatch` instances for `Proxy`
+* Fix lower bound on `mtl`
+* Increase upper bound on `optparse-applicative`
+
+4.2.0
+
+* BREAKING CHANGE: Switch from `ErrorT` to `ExceptT`
+* Add `Foldable` instance for `ListT`
+* Fix all warnings
+* Enable foldr/build fusion for `toList`
+
+4.1.9
+
+* Increase lower bound on `criterion`
+* Increase upper bound on `transformers` for tests/benchmarks
+* Optimize code by delaying `INLINABLE` annotations
+
+4.1.8
+
+* Increase upper bound on `transformers`
+* Prepare for MRP (Monad of no Return Proposal)
+
+4.1.7
+
+* Increase lower bound on `deepseq`
+* Add `unfoldr`
+* Add `loop`
+* Add `toListM'`
+* Improve efficiency of `drop`
+* License tutorial under Creative Commons license
+
+4.1.6
+
+* Increase lower bound on `base`
+* Add diagrams to `Pipes.Core` documentation
+* Add `mapM_`
+* Add `takeWhile'`
+* Add `seq`
+* Improve efficiency of `toListM`
+
+4.1.5
+
+* Increase upper bound on `criterion`
+
+4.1.4
+
+* Increase upper bound on `criterion`
+* Add `Monoid` instance for `Proxy`
+
+4.1.3
+
+* Increase lower bound on `mtl`
+* Re-export `void`
+* Add `fold'`
+* Add `foldM'`
+
+4.1.2
+
+* Increase upper bounds on `transformers` and `mtl`
+
+4.1.1
+
+* Add `runListT`
+* Add `MMonad` instance for `Proxy`
+* Add `repeatM`
+* Add laws to documentation of `Pipes.Prelude` utilities
+
+4.1.0
+
+* Remove Haskell98 support
+* Use internal `X` type instead of `Data.Void`
+* Document `Pipes.Lift` module:w
+* Add `drain`
+* Add `sequence`
+
+4.0.2
+
+* Improve performance of `each`
+* Add tutorial appendix explaining how to work around quadratic time complexity
+
+4.0.1
+
+* Remove `WriterT` and `RWST` benchmarks
+* Add `Enumerable` instance for `ErrorT`
+* Add cabal flag for Haskell98 compilation
+* Add several rewrite rules
+* Add `mtl` instances for `ListT`
+* Fix implementation of `pass`, which did not satisfy `Writer` laws
+* Implement `fail` for `ListT`
+* Add type synonym table to tutorial appendix
+* Add QuickCheck tests for `pipes` laws
+* Add `mapFoldable`
+* Add `Monoid` instance for `ListT`
+* Add manual proofs of `pipes` laws in `laws.md`
+
+4.0.0
+
+Major upgrade of `pipes` to no longer use `Proxy` type class
diff --git a/pipes.cabal b/pipes.cabal
--- a/pipes.cabal
+++ b/pipes.cabal
@@ -1,8 +1,8 @@
 Name: pipes
-Version: 4.2.0
+Version: 4.3.16
 Cabal-Version: >= 1.10
 Build-Type: Simple
-Tested-With: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.2, GHC == 8.0.1
+Tested-With: GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.5, GHC == 8.8.1
 License: BSD3
 License-File: LICENSE
 Copyright: 2012-2016 Gabriel Gonzalez
@@ -35,6 +35,8 @@
   .
   Read "Pipes.Tutorial" for an extensive tutorial.
 Category: Control, Pipes
+Extra-Source-Files:
+    CHANGELOG.md
 Source-Repository head
     Type: git
     Location: https://github.com/Gabriel439/Haskell-Pipes-Library
@@ -44,11 +46,18 @@
 
     HS-Source-Dirs: src
     Build-Depends:
-        base         >= 4.4     && < 5  ,
-        transformers >= 0.2.0.0 && < 0.6,
-        mmorph       >= 1.0.0   && < 1.1,
-        mtl          >= 2.1     && < 2.3
+        base         >= 4.8     && < 5   ,
+        transformers >= 0.2.0.0 && < 0.6 ,
+        exceptions   >= 0.4     && < 0.11,
+        mmorph       >= 1.0.4   && < 1.2 ,
+        mtl          >= 2.2.1   && < 2.3 ,
+        void         >= 0.4     && < 0.8
 
+    if impl(ghc < 8.0)
+        Build-depends:
+            fail       == 4.9.*         ,
+            semigroups >= 0.17 && < 0.20
+
     Exposed-Modules:
         Pipes,
         Pipes.Core,
@@ -68,8 +77,8 @@
 
     Build-Depends:
         base      >= 4.4     && < 5  ,
-        criterion >= 1.1.1.0 && < 1.2,
-        optparse-applicative >= 0.12 && < 0.13,
+        criterion >= 1.1.1.0 && < 1.6,
+        optparse-applicative >= 0.12 && < 0.17,
         mtl       >= 2.1     && < 2.3,
         pipes
 
@@ -99,8 +108,8 @@
 
     Build-Depends:
         base                 >= 4.4     && < 5   ,
-        criterion            >= 1.1.1.0 && < 1.2 ,
-        optparse-applicative >= 0.12    && < 0.13,
+        criterion            >= 1.1.1.0 && < 1.6 ,
+        optparse-applicative >= 0.12    && < 0.17,
         mtl                  >= 2.1     && < 2.3 ,
         pipes                                    ,
         transformers         >= 0.2.0.0 && < 0.6
diff --git a/src/Pipes.hs b/src/Pipes.hs
--- a/src/Pipes.hs
+++ b/src/Pipes.hs
@@ -63,10 +63,11 @@
     , Foldable
     ) where
 
-import Control.Monad (void)
+import Control.Monad (void, MonadPlus(mzero, mplus))
+import Control.Monad.Catch (MonadThrow(..), MonadCatch(..))
 import Control.Monad.Except (MonadError(..))
+import Control.Monad.Fail (MonadFail(..))
 import Control.Monad.IO.Class (MonadIO(liftIO))
-import Control.Monad (MonadPlus(mzero, mplus))
 import Control.Monad.Reader (MonadReader(..))
 import Control.Monad.State (MonadState(..))
 import Control.Monad.Trans.Class (MonadTrans(lift))
@@ -74,6 +75,7 @@
 import Control.Monad.Trans.Identity (IdentityT(runIdentityT))
 import Control.Monad.Trans.Maybe (MaybeT(runMaybeT))
 import Control.Monad.Writer (MonadWriter(..))
+import Control.Monad.Zip (MonadZip(..))
 import Pipes.Core
 import Pipes.Internal (Proxy(..))
 import qualified Data.Foldable as F
@@ -83,11 +85,12 @@
 #else
 import Control.Applicative
 import Data.Foldable (Foldable)
-import Data.Monoid
+import Data.Traversable (Traversable(..))
 #endif
+import Data.Semigroup
 
 -- Re-exports
-import Control.Monad.Morph (MFunctor(hoist))
+import Control.Monad.Morph (MFunctor(hoist), MMonad(embed))
 
 infixl 4 <~
 infixr 4 ~>
@@ -131,20 +134,21 @@
 {-| Produce a value
 
 @
-'yield' :: 'Monad' m => a -> 'Pipe' x a m ()
+'yield' :: 'Monad' m => a -> 'Producer' a m ()
+'yield' :: 'Monad' m => a -> 'Pipe'   x a m ()
 @
 -}
-yield :: Monad m => a -> Producer' a m ()
+yield :: Functor m => a -> Proxy x' x () a m ()
 yield = respond
 {-# INLINABLE [1] yield #-}
 
 {-| @(for p body)@ loops over @p@ replacing each 'yield' with @body@.
 
 @
-'for' :: 'Monad' m => 'Producer' b m r -> (b -> 'Effect'       m ()) -> 'Effect'       m r
-'for' :: 'Monad' m => 'Producer' b m r -> (b -> 'Producer'   c m ()) -> 'Producer'   c m r
-'for' :: 'Monad' m => 'Pipe'   x b m r -> (b -> 'Consumer' x   m ()) -> 'Consumer' x   m r
-'for' :: 'Monad' m => 'Pipe'   x b m r -> (b -> 'Pipe'     x c m ()) -> 'Pipe'     x c m r
+'for' :: 'Functor' m => 'Producer' b m r -> (b -> 'Effect'       m ()) -> 'Effect'       m r
+'for' :: 'Functor' m => 'Producer' b m r -> (b -> 'Producer'   c m ()) -> 'Producer'   c m r
+'for' :: 'Functor' m => 'Pipe'   x b m r -> (b -> 'Consumer' x   m ()) -> 'Consumer' x   m r
+'for' :: 'Functor' m => 'Pipe'   x b m r -> (b -> 'Pipe'     x c m ()) -> 'Pipe'     x c m r
 @
 
     The following diagrams show the flow of information:
@@ -165,7 +169,7 @@
 
     For a more complete diagram including bidirectional flow, see "Pipes.Core#respond-diagram".
 -}
-for :: Monad m
+for :: Functor m
     =>       Proxy x' x b' b m a'
     -- ^
     -> (b -> Proxy x' x c' c m b')
@@ -218,10 +222,10 @@
 {-| Compose loop bodies
 
 @
-('~>') :: 'Monad' m => (a -> 'Producer' b m r) -> (b -> 'Effect'       m ()) -> (a -> 'Effect'       m r)
-('~>') :: 'Monad' m => (a -> 'Producer' b m r) -> (b -> 'Producer'   c m ()) -> (a -> 'Producer'   c m r)
-('~>') :: 'Monad' m => (a -> 'Pipe'   x b m r) -> (b -> 'Consumer' x   m ()) -> (a -> 'Consumer' x   m r)
-('~>') :: 'Monad' m => (a -> 'Pipe'   x b m r) -> (b -> 'Pipe'     x c m ()) -> (a -> 'Pipe'     x c m r)
+('~>') :: 'Functor' m => (a -> 'Producer' b m r) -> (b -> 'Effect'       m ()) -> (a -> 'Effect'       m r)
+('~>') :: 'Functor' m => (a -> 'Producer' b m r) -> (b -> 'Producer'   c m ()) -> (a -> 'Producer'   c m r)
+('~>') :: 'Functor' m => (a -> 'Pipe'   x b m r) -> (b -> 'Consumer' x   m ()) -> (a -> 'Consumer' x   m r)
+('~>') :: 'Functor' m => (a -> 'Pipe'   x b m r) -> (b -> 'Pipe'     x c m ()) -> (a -> 'Pipe'     x c m r)
 @
 
     The following diagrams show the flow of information:
@@ -243,7 +247,7 @@
     For a more complete diagram including bidirectional flow, see "Pipes.Core#respond-diagram".
 -}
 (~>)
-    :: Monad m
+    :: Functor m
     => (a -> Proxy x' x b' b m a')
     -- ^
     -> (b -> Proxy x' x c' c m b')
@@ -254,7 +258,7 @@
 
 -- | ('~>') with the arguments flipped
 (<~)
-    :: Monad m
+    :: Functor m
     => (b -> Proxy x' x c' c m b')
     -- ^
     -> (a -> Proxy x' x b' b m a')
@@ -284,20 +288,20 @@
 {-| Consume a value
 
 @
-'await' :: 'Monad' m => 'Pipe' a y m a
+'await' :: 'Functor' m => 'Pipe' a y m a
 @
 -}
-await :: Monad m => Consumer' a m a
+await :: Functor m => Consumer' a m a
 await = request ()
 {-# INLINABLE [1] await #-}
 
 {-| @(draw >~ p)@ loops over @p@ replacing each 'await' with @draw@
 
 @
-('>~') :: 'Monad' m => 'Effect'       m b -> 'Consumer' b   m c -> 'Effect'       m c
-('>~') :: 'Monad' m => 'Consumer' a   m b -> 'Consumer' b   m c -> 'Consumer' a   m c
-('>~') :: 'Monad' m => 'Producer'   y m b -> 'Pipe'     b y m c -> 'Producer'   y m c
-('>~') :: 'Monad' m => 'Pipe'     a y m b -> 'Pipe'     b y m c -> 'Pipe'     a y m c
+('>~') :: 'Functor' m => 'Effect'       m b -> 'Consumer' b   m c -> 'Effect'       m c
+('>~') :: 'Functor' m => 'Consumer' a   m b -> 'Consumer' b   m c -> 'Consumer' a   m c
+('>~') :: 'Functor' m => 'Producer'   y m b -> 'Pipe'     b y m c -> 'Producer'   y m c
+('>~') :: 'Functor' m => 'Pipe'     a y m b -> 'Pipe'     b y m c -> 'Pipe'     a y m c
 @
 
     The following diagrams show the flow of information:
@@ -317,7 +321,7 @@
     For a more complete diagram including bidirectional flow, see "Pipes.Core#request-diagram".
 -}
 (>~)
-    :: Monad m
+    :: Functor m
     => Proxy a' a y' y m b
     -- ^
     -> Proxy () b y' y m c
@@ -328,7 +332,7 @@
 
 -- | ('>~') with the arguments flipped
 (~<)
-    :: Monad m
+    :: Functor m
     => Proxy () b y' y m c
     -- ^
     -> Proxy a' a y' y m b
@@ -356,17 +360,17 @@
 -}
 
 -- | The identity 'Pipe', analogous to the Unix @cat@ program
-cat :: Monad m => Pipe a a m r
+cat :: Functor m => Pipe a a m r
 cat = pull ()
 {-# INLINABLE [1] cat #-}
 
 {-| 'Pipe' composition, analogous to the Unix pipe operator
 
 @
-('>->') :: 'Monad' m => 'Producer' b m r -> 'Consumer' b   m r -> 'Effect'       m r
-('>->') :: 'Monad' m => 'Producer' b m r -> 'Pipe'     b c m r -> 'Producer'   c m r
-('>->') :: 'Monad' m => 'Pipe'   a b m r -> 'Consumer' b   m r -> 'Consumer' a   m r
-('>->') :: 'Monad' m => 'Pipe'   a b m r -> 'Pipe'     b c m r -> 'Pipe'     a c m r
+('>->') :: 'Functor' m => 'Producer' b m r -> 'Consumer' b   m r -> 'Effect'       m r
+('>->') :: 'Functor' m => 'Producer' b m r -> 'Pipe'     b c m r -> 'Producer'   c m r
+('>->') :: 'Functor' m => 'Pipe'   a b m r -> 'Consumer' b   m r -> 'Consumer' a   m r
+('>->') :: 'Functor' m => 'Pipe'   a b m r -> 'Pipe'     b c m r -> 'Pipe'     a c m r
 @
 
     The following diagrams show the flow of information:
@@ -386,7 +390,7 @@
     For a more complete diagram including bidirectional flow, see "Pipes.Core#pull-diagram".
 -}
 (>->)
-    :: Monad m
+    :: Functor m
     => Proxy a' a () b m r
     -- ^
     -> Proxy () b c' c m r
@@ -397,29 +401,69 @@
 
 {-| The list monad transformer, which extends a monad with non-determinism
 
-    'return' corresponds to 'yield', yielding a single value
+    The type variables signify:
 
-    ('>>=') corresponds to 'for', calling the second computation once for each
-    time the first computation 'yield's.
+      * @m@ - The base monad
+      * @a@ - The values that the computation 'yield's throughout its execution
+
+    For basic construction and composition of 'ListT' computations, much can be
+    accomplished using common typeclass methods.
+
+      * 'return' corresponds to 'yield', yielding a single value.
+      * ('>>=') corresponds to 'for', calling the second computation once
+        for each time the first computation 'yield's.
+      * 'mempty' neither 'yield's any values nor produces any effects in the
+        base monad.
+      * ('<>') sequences two computations, 'yield'ing all the values of the
+        first followed by all the values of the second.
+      * 'lift' converts an action in the base monad into a ListT computation
+        which performs the action and 'yield's a single value.
+
+    'ListT' is a newtype wrapper for 'Producer'. You will likely need to use
+    'Select' and 'enumerate' to convert back and forth between these two types
+    to take advantage of all the 'Producer'-related utilities that
+    "Pipes.Prelude" has to offer.
+
+      * To lift a plain list into a 'ListT' computation, first apply 'each'
+        to turn the list into a 'Producer'. Then apply the 'Select'
+        constructor to convert from 'Producer' to 'ListT'.
+      * For other ways to construct 'ListT' computations, see the
+        “Producers” section in "Pipes.Prelude" to build 'Producer's.
+        These can then be converted to 'ListT' using 'Select'.
+      * To aggregate the values from a 'ListT' computation (for example,
+        to compute the sum of a 'ListT' of numbers), first apply
+        'enumerate' to obtain a 'Producer'. Then see the “Folds”
+        section in "Pipes.Prelude" to proceed.
 -}
 newtype ListT m a = Select { enumerate :: Producer a m () }
 
-instance (Monad m) => Functor (ListT m) where
+instance Functor m => Functor (ListT m) where
     fmap f p = Select (for (enumerate p) (\a -> yield (f a)))
+    {-# INLINE fmap #-}
 
-instance (Monad m) => Applicative (ListT m) where
+instance Functor m => Applicative (ListT m) where
     pure a = Select (yield a)
+    {-# INLINE pure #-}
     mf <*> mx = Select (
         for (enumerate mf) (\f ->
         for (enumerate mx) (\x ->
         yield (f x) ) ) )
 
-instance (Monad m) => Monad (ListT m) where
+instance Monad m => Monad (ListT m) where
     return   = pure
+    {-# INLINE return #-}
     m >>= f  = Select (for (enumerate m) (\a -> enumerate (f a)))
+    {-# INLINE (>>=) #-}
+#if !MIN_VERSION_base(4,13,0)
     fail _   = mzero
+    {-# INLINE fail #-}
+#endif
 
-instance (Foldable m) => Foldable (ListT m) where
+instance Monad m => MonadFail (ListT m) where
+    fail _ = mzero
+    {-# INLINE fail #-}
+
+instance Foldable m => Foldable (ListT m) where
     foldMap f = go . enumerate
       where
         go p = case p of
@@ -429,6 +473,16 @@
             Pure    _    -> mempty
     {-# INLINE foldMap #-}
 
+instance (Functor m, Traversable m) => Traversable (ListT m) where
+    traverse k (Select p) = fmap Select (traverse_ p)
+      where
+        traverse_ (Request v _ ) = closed v
+        traverse_ (Respond a fu) = _Respond <$> k a <*> traverse_ (fu ())
+          where
+            _Respond a_ a' = Respond a_ (\_ -> a')
+        traverse_ (M       m   ) = fmap M (traverse traverse_ m)
+        traverse_ (Pure     r  ) = pure (Pure r)
+
 instance MonadTrans ListT where
     lift m = Select (do
         a <- lift m
@@ -436,35 +490,62 @@
 
 instance (MonadIO m) => MonadIO (ListT m) where
     liftIO m = lift (liftIO m)
+    {-# INLINE liftIO #-}
 
-instance (Monad m) => Alternative (ListT m) where
+instance (Functor m) => Alternative (ListT m) where
     empty = Select (return ())
+    {-# INLINE empty #-}
     p1 <|> p2 = Select (do
         enumerate p1
         enumerate p2 )
 
 instance (Monad m) => MonadPlus (ListT m) where
     mzero = empty
+    {-# INLINE mzero #-}
     mplus = (<|>)
+    {-# INLINE mplus #-}
 
 instance MFunctor ListT where
     hoist morph = Select . hoist morph . enumerate
+    {-# INLINE hoist #-}
 
-instance (Monad m) => Monoid (ListT m a) where
+instance MMonad ListT where
+    embed f (Select p0) = Select (loop p0)
+      where
+        loop (Request a' fa ) = Request a' (\a  -> loop (fa  a ))
+        loop (Respond b  fb') = Respond b  (\b' -> loop (fb' b'))
+        loop (M          m  ) = for (enumerate (fmap loop (f m))) id
+        loop (Pure    r     ) = Pure r
+    {-# INLINE embed #-}
+
+instance (Functor m) => Semigroup (ListT m a) where
+    (<>) = (<|>)
+    {-# INLINE (<>) #-}
+
+instance (Functor m) => Monoid (ListT m a) where
     mempty = empty
+    {-# INLINE mempty #-}
+#if !(MIN_VERSION_base(4,11,0))
     mappend = (<|>)
+    {-# INLINE mappend #-}
+#endif
 
 instance (MonadState s m) => MonadState s (ListT m) where
     get     = lift  get
+    {-# INLINE get #-}
 
     put   s = lift (put   s)
+    {-# INLINE put #-}
 
     state f = lift (state f)
+    {-# INLINE state #-}
 
 instance (MonadWriter w m) => MonadWriter w (ListT m) where
     writer = lift . writer
+    {-# INLINE writer #-}
 
     tell w = lift (tell w)
+    {-# INLINE tell #-}
 
     listen l = Select (go (enumerate l) mempty)
       where
@@ -489,16 +570,44 @@
 
 instance (MonadReader i m) => MonadReader i (ListT m) where
     ask = lift ask
+    {-# INLINE ask #-}
 
     local f l = Select (local f (enumerate l))
+    {-# INLINE local #-}
 
     reader f = lift (reader f)
+    {-# INLINE reader #-}
 
 instance (MonadError e m) => MonadError e (ListT m) where
     throwError e = lift (throwError e)
+    {-# INLINE throwError #-}
 
     catchError l k = Select (catchError (enumerate l) (\e -> enumerate (k e)))
+    {-# INLINE catchError #-}
 
+instance MonadThrow m => MonadThrow (ListT m) where
+    throwM = Select . throwM
+    {-# INLINE throwM #-}
+
+instance MonadCatch m => MonadCatch (ListT m) where
+    catch l k = Select (Control.Monad.Catch.catch (enumerate l) (\e -> enumerate (k e)))
+    {-# INLINE catch #-}
+
+instance Monad m => MonadZip (ListT m) where
+    mzipWith f = go
+      where
+        go xs ys = Select $ do
+            xres <- lift $ next (enumerate xs)
+            case xres of
+                Left r -> return r
+                Right (x, xnext) -> do
+                    yres <- lift $ next (enumerate ys)
+                    case yres of
+                        Left r -> return r
+                        Right (y, ynext) -> do
+                            yield (f x y)
+                            enumerate (go (Select xnext) (Select ynext))
+
 -- | Run a self-contained `ListT` computation
 runListT :: Monad m => ListT m a -> m ()
 runListT l = runEffect (enumerate (l >> mzero))
@@ -556,8 +665,13 @@
         Pure    r    -> return (Left r)
 {-# INLINABLE next #-}
 
--- | Convert a 'F.Foldable' to a 'Producer'
-each :: (Monad m, Foldable f) => f a -> Producer' a m ()
+{-| Convert a 'F.Foldable' to a 'Producer'
+
+@
+'each' :: ('Functor' m, 'Foldable' f) => f a -> 'Producer' a m ()
+@
+-}
+each :: (Functor m, Foldable f) => f a -> Proxy x' x () a m ()
 each = F.foldr (\a p -> yield a >> p) (return ())
 {-# INLINABLE each #-}
 {-  The above code is the same as:
@@ -568,8 +682,13 @@
     build/foldr fusion
 -}
 
--- | Convert an 'Enumerable' to a 'Producer'
-every :: (Monad m, Enumerable t) => t m a -> Producer' a m ()
+{-| Convert an 'Enumerable' to a 'Producer'
+
+@
+'every' :: ('Monad' m, 'Enumerable' t) => t m a -> 'Producer' a m ()
+@
+-}
+every :: (Monad m, Enumerable t) => t m a -> Proxy x' x () a m ()
 every it = discard >\\ enumerate (toListT it)
 {-# INLINABLE every #-}
 
@@ -580,7 +699,7 @@
 
 -- | ('>->') with the arguments flipped
 (<-<)
-    :: Monad m
+    :: Functor m
     => Proxy () b c' c m r
     -- ^
     -> Proxy a' a () b m r
diff --git a/src/Pipes/Core.hs b/src/Pipes/Core.hs
--- a/src/Pipes/Core.hs
+++ b/src/Pipes/Core.hs
@@ -221,7 +221,7 @@
     The following diagrams show the flow of information:
 
 @
-'respond' :: 'Monad' m
+'respond' :: 'Functor' m
        =>  a -> 'Proxy' x' x a' a m a'
 
 \          a
@@ -236,7 +236,7 @@
           v
           a'
 
-('/>/') :: 'Monad' m
+('/>/') :: 'Functor' m
       => (a -> 'Proxy' x' x b' b m a')
       -> (b -> 'Proxy' x' x c' c m b')
       -> (a -> 'Proxy' x' x c' c m a')
@@ -247,13 +247,13 @@
      |    v    |           /   |    v    |            |    v    |
  x' <==       <== b' <==\\ / x'<==       <== c'    x' <==       <== c'
      |    f    |         X     |    g    |     =      | f '/>/' g |
- x  ==>       ==> b  ===/ \\ x ==>       ==> c     x  ==>       ==> c'
+ x  ==>       ==> b  ===/ \\ x ==>       ==> c     x  ==>       ==> c
      |    |    |           \\   |    |    |            |    |    |
      +----|----+            \\  +----|----+            +----|----+
           v                  \\      v                      v
           a'                  \\==== b'                     a'
 
-('//>') :: 'Monad' m
+('//>') :: 'Functor' m
       => 'Proxy' x' x b' b m a'
       -> (b -> 'Proxy' x' x c' c m b')
       -> 'Proxy' x' x c' c m a'
@@ -278,7 +278,7 @@
 
     'respond' is the identity of the respond category.
 -}
-respond :: Monad m => a -> Proxy x' x a' a m a'
+respond :: Functor m => a -> Proxy x' x a' a m a'
 respond a = Respond a Pure
 {-# INLINABLE [1] respond #-}
 
@@ -291,7 +291,7 @@
     ('/>/') is the composition operator of the respond category.
 -}
 (/>/)
-    :: Monad m
+    :: Functor m
     => (a -> Proxy x' x b' b m a')
     -- ^
     -> (b -> Proxy x' x c' c m b')
@@ -306,7 +306,7 @@
     Point-ful version of ('/>/')
 -}
 (//>)
-    :: Monad m
+    :: Functor m
     =>       Proxy x' x b' b m a'
     -- ^
     -> (b -> Proxy x' x c' c m b')
@@ -318,7 +318,7 @@
     go p = case p of
         Request x' fx  -> Request x' (\x -> go (fx x))
         Respond b  fb' -> fb b >>= \b' -> go (fb' b')
-        M          m   -> M (m >>= \p' -> return (go p'))
+        M          m   -> M (go <$> m)
         Pure       a   -> Pure a
 {-# INLINE [1] (//>) #-}
 
@@ -328,7 +328,7 @@
     "(Respond b  fb') //> fb" forall b  fb' fb .
         (Respond b  fb') //> fb = fb b >>= \b' -> fb' b' //> fb;
     "(M          m  ) //> fb" forall    m   fb .
-        (M          m  ) //> fb = M (m >>= \p' -> return (p' //> fb));
+        (M          m  ) //> fb = M ((\p' -> p' //> fb) <$> m);
     "(Pure      a   ) //> fb" forall a      fb .
         (Pure    a     ) //> fb = Pure a;
   #-}
@@ -355,7 +355,7 @@
     The following diagrams show the flow of information:
 
 @
-'request' :: 'Monad' m
+'request' :: 'Functor' m
         =>  a' -> 'Proxy' a' a y' y m a
 
 \          a'
@@ -370,7 +370,7 @@
           v
           a
 
-('\>\') :: 'Monad' m
+('\>\') :: 'Functor' m
       => (b' -> 'Proxy' a' a y' y m b)
       -> (c' -> 'Proxy' b' b y' y m c)
       -> (c' -> 'Proxy' a' a y' y m c)
@@ -387,7 +387,7 @@
           v        /               v                      v
           b ======/                c                      c
 
-('>\\') :: Monad m
+('>\\') :: Functor m
       => (b' -> Proxy a' a y' y m b)
       -> Proxy b' b y' y m c
       -> Proxy a' a y' y m c
@@ -410,7 +410,7 @@
 
     'request' is the identity of the request category.
 -}
-request :: Monad m => a' -> Proxy a' a y' y m a
+request :: Functor m => a' -> Proxy a' a y' y m a
 request a' = Request a' Pure
 {-# INLINABLE [1] request #-}
 
@@ -423,7 +423,7 @@
     ('\>\') is the composition operator of the request category.
 -}
 (\>\)
-    :: Monad m
+    :: Functor m
     => (b' -> Proxy a' a y' y m b)
     -- ^
     -> (c' -> Proxy b' b y' y m c)
@@ -438,7 +438,7 @@
     Point-ful version of ('\>\')
 -}
 (>\\)
-    :: Monad m
+    :: Functor m
     => (b' -> Proxy a' a y' y m b)
     -- ^
     ->        Proxy b' b y' y m c
@@ -450,7 +450,7 @@
     go p = case p of
         Request b' fb  -> fb' b' >>= \b -> go (fb b)
         Respond x  fx' -> Respond x (\x' -> go (fx' x'))
-        M          m   -> M (m >>= \p' -> return (go p'))
+        M          m   -> M (go <$> m)
         Pure       a   -> Pure a
 {-# INLINE [1] (>\\) #-}
 
@@ -460,7 +460,7 @@
     "fb' >\\ (Respond x  fx')" forall fb' x  fx' .
         fb' >\\ (Respond x  fx') = Respond x (\x' -> fb' >\\ fx' x');
     "fb' >\\ (M          m  )" forall fb'    m   .
-        fb' >\\ (M          m  ) = M (m >>= \p' -> return (fb' >\\ p'));
+        fb' >\\ (M          m  ) = M ((\p' -> fb' >\\ p') <$> m);
     "fb' >\\ (Pure    a    )" forall fb' a      .
         fb' >\\ (Pure    a     ) = Pure a;
   #-}
@@ -485,7 +485,7 @@
     The following diagram shows the flow of information:
 
 @
-'push'  :: 'Monad' m
+'push'  :: 'Functor' m
       =>  a -> 'Proxy' a' a a' a m r
 
 \          a
@@ -500,7 +500,7 @@
           v
           r
 
-('>~>') :: 'Monad' m
+('>~>') :: 'Functor' m
       => (a -> 'Proxy' a' a b' b m r)
       -> (b -> 'Proxy' b' b c' c m r)
       -> (a -> 'Proxy' a' a c' c m r)
@@ -528,7 +528,7 @@
 
     'push' is the identity of the push category.
 -}
-push :: Monad m => a -> Proxy a' a a' a m r
+push :: Functor m => a -> Proxy a' a a' a m r
 push = go
   where
     go a = Respond a (\a' -> Request a' go)
@@ -544,7 +544,7 @@
     ('>~>') is the composition operator of the push category.
 -}
 (>~>)
-    :: Monad m
+    :: Functor m
     => (_a -> Proxy a' a b' b m r)
     -- ^
     -> ( b -> Proxy b' b c' c m r)
@@ -559,7 +559,7 @@
     Point-ful version of ('>~>')
 -}
 (>>~)
-    :: Monad m
+    :: Functor m
     =>       Proxy a' a b' b m r
     -- ^
     -> (b -> Proxy b' b c' c m r)
@@ -569,7 +569,7 @@
 p >>~ fb = case p of
     Request a' fa  -> Request a' (\a -> fa a >>~ fb)
     Respond b  fb' -> fb' +>> fb b
-    M          m   -> M (m >>= \p' -> return (p' >>~ fb))
+    M          m   -> M ((\p' -> p' >>~ fb) <$> m)
     Pure       r   -> Pure r
 {-# INLINE [1] (>>~) #-}
 
@@ -595,7 +595,7 @@
     The following diagrams show the flow of information:
 
 @
-'pull'  :: 'Monad' m
+'pull'  :: 'Functor' m
       =>  a' -> 'Proxy' a' a a' a m r
 
 \          a'
@@ -610,7 +610,7 @@
           v
           r
 
-('>+>') :: 'Monad' m
+('>+>') :: 'Functor' m
       -> (b' -> 'Proxy' a' a b' b m r)
       -> (c' -> 'Proxy' b' b c' c m r)
       -> (c' -> 'Proxy' a' a c' c m r)
@@ -638,7 +638,7 @@
 
     'pull' is the identity of the pull category.
 -}
-pull :: Monad m => a' -> Proxy a' a a' a m r
+pull :: Functor m => a' -> Proxy a' a a' a m r
 pull = go
   where
     go a' = Request a' (\a -> Respond a go)
@@ -654,7 +654,7 @@
     ('>+>') is the composition operator of the pull category.
 -}
 (>+>)
-    :: Monad m
+    :: Functor m
     => ( b' -> Proxy a' a b' b m r)
     -- ^
     -> (_c' -> Proxy b' b c' c m r)
@@ -669,7 +669,7 @@
     Point-ful version of ('>+>')
 -}
 (+>>)
-    :: Monad m
+    :: Functor m
     => (b' -> Proxy a' a b' b m r)
     -- ^
     ->        Proxy b' b c' c m r
@@ -679,7 +679,7 @@
 fb' +>> p = case p of
     Request b' fb  -> fb' b' >>~ fb
     Respond c  fc' -> Respond c (\c' -> fb' +>> fc' c')
-    M          m   -> M (m >>= \p' -> return (fb' +>> p'))
+    M          m   -> M ((\p' -> fb' +>> p') <$> m)
     Pure       r   -> Pure r
 {-# INLINABLE [1] (+>>) #-}
 
@@ -716,13 +716,13 @@
 -}
 
 -- | Switch the upstream and downstream ends
-reflect :: Monad m => Proxy a' a b' b m r -> Proxy b b' a a' m r
+reflect :: Functor m => Proxy a' a b' b m r -> Proxy b b' a a' m r
 reflect = go
   where
     go p = case p of
         Request a' fa  -> Respond a' (\a  -> go (fa  a ))
         Respond b  fb' -> Request b  (\b' -> go (fb' b'))
-        M          m   -> M (m >>= \p' -> return (go p'))
+        M          m   -> M (go <$> m)
         Pure    r      -> Pure r
 {-# INLINABLE reflect #-}
 
@@ -772,7 +772,7 @@
 
 -- | Equivalent to ('/>/') with the arguments flipped
 (\<\)
-    :: Monad m
+    :: Functor m
     => (b -> Proxy x' x c' c m b')
     -- ^
     -> (a -> Proxy x' x b' b m a')
@@ -784,7 +784,7 @@
 
 -- | Equivalent to ('\>\') with the arguments flipped
 (/</)
-    :: Monad m
+    :: Functor m
     => (c' -> Proxy b' b x' x m c)
     -- ^
     -> (b' -> Proxy a' a x' x m b)
@@ -796,7 +796,7 @@
 
 -- | Equivalent to ('>~>') with the arguments flipped
 (<~<)
-    :: Monad m
+    :: Functor m
     => (b -> Proxy b' b c' c m r)
     -- ^
     -> (a -> Proxy a' a b' b m r)
@@ -808,7 +808,7 @@
 
 -- | Equivalent to ('>+>') with the arguments flipped
 (<+<)
-    :: Monad m
+    :: Functor m
     => (c' -> Proxy b' b c' c m r)
     -- ^
     -> (b' -> Proxy a' a b' b m r)
@@ -820,7 +820,7 @@
 
 -- | Equivalent to ('//>') with the arguments flipped
 (<\\)
-    :: Monad m
+    :: Functor m
     => (b -> Proxy x' x c' c m b')
     -- ^
     ->       Proxy x' x b' b m a'
@@ -832,7 +832,7 @@
 
 -- | Equivalent to ('>\\') with the arguments flipped
 (//<)
-    :: Monad m
+    :: Functor m
     =>        Proxy b' b y' y m c
     -- ^
     -> (b' -> Proxy a' a y' y m b)
@@ -844,7 +844,7 @@
 
 -- | Equivalent to ('>>~') with the arguments flipped
 (~<<)
-    :: Monad m
+    :: Functor m
     => (b  -> Proxy b' b c' c m r)
     -- ^
     ->        Proxy a' a b' b m r
@@ -856,7 +856,7 @@
 
 -- | Equivalent to ('+>>') with the arguments flipped
 (<<+)
-    :: Monad m
+    :: Functor m
     =>         Proxy b' b c' c m r
     -- ^
     -> (b'  -> Proxy a' a b' b m r)
diff --git a/src/Pipes/Internal.hs b/src/Pipes/Internal.hs
--- a/src/Pipes/Internal.hs
+++ b/src/Pipes/Internal.hs
@@ -34,22 +34,26 @@
     , closed
     ) where
 
-import Control.Monad (MonadPlus(..))
+import qualified Control.Monad.Fail as F (MonadFail(fail))
 import Control.Monad.IO.Class (MonadIO(liftIO))
 import Control.Monad.Trans.Class (MonadTrans(lift))
 import Control.Monad.Morph (MFunctor(hoist), MMonad(embed))
 import Control.Monad.Except (MonadError(..))
+import Control.Monad.Catch (MonadThrow(..), MonadCatch(..))
 import Control.Monad.Reader (MonadReader(..))
 import Control.Monad.State (MonadState(..))
-import Control.Monad.Writer (MonadWriter(..))
+import Control.Monad.Writer (MonadWriter(..), censor)
+import Data.Void (Void)
 
 #if MIN_VERSION_base(4,8,0)
 import Control.Applicative (Alternative(..))
 #else
 import Control.Applicative
-import Data.Monoid
 #endif
+import Data.Semigroup
 
+import qualified Data.Void
+
 {-| A 'Proxy' is a monad transformer that receives and sends information on both
     an upstream and downstream interface.
 
@@ -71,30 +75,35 @@
     | M          (m    (Proxy a' a b' b m r))
     | Pure    r
 
-instance Monad m => Functor (Proxy a' a b' b m) where
+instance Functor m => Functor (Proxy a' a b' b m) where
     fmap f p0 = go p0 where
         go p = case p of
             Request a' fa  -> Request a' (\a  -> go (fa  a ))
             Respond b  fb' -> Respond b  (\b' -> go (fb' b'))
-            M          m   -> M (m >>= \p' -> return (go p'))
+            M          m   -> M (go <$> m)
             Pure    r      -> Pure (f r)
 
-instance Monad m => Applicative (Proxy a' a b' b m) where
+instance Functor m => Applicative (Proxy a' a b' b m) where
     pure      = Pure
     pf <*> px = go pf where
         go p = case p of
             Request a' fa  -> Request a' (\a  -> go (fa  a ))
             Respond b  fb' -> Respond b  (\b' -> go (fb' b'))
-            M          m   -> M (m >>= \p' -> return (go p'))
+            M          m   -> M (go <$> m)
             Pure    f      -> fmap f px
-    m *> k = m >>= (\_ -> k)
+    l *> r = go l where
+        go p = case p of
+            Request a' fa  -> Request a' (\a  -> go (fa  a ))
+            Respond b  fb' -> Respond b  (\b' -> go (fb' b'))
+            M          m   -> M (go <$> m)
+            Pure    _      -> r
 
-instance Monad m => Monad (Proxy a' a b' b m) where
+instance Functor m => Monad (Proxy a' a b' b m) where
     return = pure
     (>>=)  = _bind
 
 _bind
-    :: Monad m
+    :: Functor m
     => Proxy a' a b' b m r
     -> (r -> Proxy a' a b' b m r')
     -> Proxy a' a b' b m r'
@@ -102,7 +111,7 @@
     go p = case p of
         Request a' fa  -> Request a' (\a  -> go (fa  a ))
         Respond b  fb' -> Respond b  (\b' -> go (fb' b'))
-        M          m   -> M (m >>= \p' -> return (go p'))
+        M          m   -> M (go <$> m)
         Pure    r      -> f r
 {-# NOINLINE[1] _bind #-}
 
@@ -112,22 +121,27 @@
     "_bind (Respond b  k) f" forall b  k f .
         _bind (Respond b  k) f = Respond b  (\b' -> _bind (k b') f);
     "_bind (M          m) f" forall m    f .
-        _bind (M          m) f = M (m >>= \p -> return (_bind p f));
+        _bind (M          m) f = M ((\p -> _bind p f) <$> m);
     "_bind (Pure    r   ) f" forall r    f .
         _bind (Pure    r   ) f = f r;
   #-}
 
-instance (Monad m, Monoid r) => Monoid (Proxy a' a b' b m r) where
-    mempty        = Pure mempty
-    mappend p1 p2 = go p1 where
+instance (Functor m, Semigroup r) => Semigroup (Proxy a' a b' b m r) where
+    p1 <> p2 = go p1 where
         go p = case p of
             Request a' fa  -> Request a' (\a  -> go (fa  a ))
             Respond b  fb' -> Respond b  (\b' -> go (fb' b'))
-            M          m   -> M (m >>= \p' -> return (go p'))
-            Pure    r1     -> fmap (mappend r1) p2
+            M          m   -> M (go <$> m)
+            Pure    r1     -> fmap (r1 <>) p2
 
+instance (Functor m, Monoid r, Semigroup r) => Monoid (Proxy a' a b' b m r) where
+    mempty        = Pure mempty
+#if !(MIN_VERSION_base(4,11,0))
+    mappend = (<>)
+#endif
+
 instance MonadTrans (Proxy a' a b' b) where
-    lift m = M (m >>= \r -> return (Pure r))
+    lift m = M (Pure <$> m)
 
 {-| 'unsafeHoist' is like 'hoist', but faster.
 
@@ -136,14 +150,14 @@
     safe if you pass a monad morphism as the first argument.
 -}
 unsafeHoist
-    :: Monad m
+    :: Functor m
     => (forall x . m x -> n x) -> Proxy a' a b' b m r -> Proxy a' a b' b n r
 unsafeHoist nat = go
   where
     go p = case p of
         Request a' fa  -> Request a' (\a  -> go (fa  a ))
         Respond b  fb' -> Respond b  (\b' -> go (fb' b'))
-        M          m   -> M (nat (m >>= \p' -> return (go p')))
+        M          m   -> M (nat (go <$> m))
         Pure    r      -> Pure r
 {-# INLINABLE unsafeHoist #-}
 
@@ -153,7 +167,7 @@
         go p = case p of
             Request a' fa  -> Request a' (\a  -> go (fa  a ))
             Respond b  fb' -> Respond b  (\b' -> go (fb' b'))
-            M          m   -> M (nat (m >>= \p' -> return (go p')))
+            M          m   -> M (nat (go <$> m))
             Pure    r      -> Pure r
 
 instance MMonad (Proxy a' a b' b) where
@@ -165,8 +179,11 @@
             M          m   -> f m >>= go
             Pure    r      -> Pure r
 
+instance F.MonadFail m => F.MonadFail (Proxy a' a b' b m) where
+    fail = lift . F.fail
+
 instance MonadIO m => MonadIO (Proxy a' a b' b m) where
-    liftIO m = M (liftIO (m >>= \r -> return (Pure r)))
+    liftIO m = M (liftIO (Pure <$> m))
 
 instance MonadReader r m => MonadReader r (Proxy a' a b' b m) where
     ask = lift ask
@@ -176,7 +193,7 @@
               Request a' fa  -> Request a' (\a  -> go (fa  a ))
               Respond b  fb' -> Respond b  (\b' -> go (fb' b'))
               Pure    r      -> Pure r
-              M       m      -> M (local f m >>= \r -> return (go r))
+              M       m      -> M (go <$> local f m)
     reader = lift . reader
 
 instance MonadState s m => MonadState s (Proxy a' a b' b m) where
@@ -203,7 +220,7 @@
             Request a' fa  -> Request a' (\a  -> go (fa  a ) w)
             Respond b  fb' -> Respond b  (\b' -> go (fb' b') w)
             M       m      -> M (do
-                (p', w') <- listen m
+                (p', w') <- censor (const mempty) (listen m)
                 return (go p' $! mappend w w') )
             Pure   (r, f)  -> M (pass (return (Pure r, \_ -> f w)))
 
@@ -219,13 +236,12 @@
                 p' <- m
                 return (go p') ) `catchError` (\e -> return (f e)) )
 
-instance MonadPlus m => Alternative (Proxy a' a b' b m) where
-    empty = mzero
-    (<|>) = mplus
+instance MonadThrow m => MonadThrow (Proxy a' a b' b m) where
+    throwM = lift . throwM
+    {-# INLINE throwM #-}
 
-instance MonadPlus m => MonadPlus (Proxy a' a b' b m) where
-    mzero = lift mzero
-    mplus p0 p1 = go p0
+instance MonadCatch m => MonadCatch (Proxy a' a b' b m) where
+    catch p0 f = go p0
       where
         go p = case p of
             Request a' fa  -> Request a' (\a  -> go (fa  a ))
@@ -233,7 +249,7 @@
             Pure    r      -> Pure r
             M          m   -> M ((do
                 p' <- m
-                return (go p') ) `mplus` return p1 )
+                return (go p') ) `Control.Monad.Catch.catch` (\e -> return (f e)) )
 
 {-| The monad transformer laws are correct when viewed through the 'observe'
     function:
@@ -259,15 +275,10 @@
         Pure    r      -> return (Pure r)
 {-# INLINABLE observe #-}
 
-{-| The empty type, used to close output ends
-
-    When @Data.Void@ is merged into @base@, this will change to:
-
-> type X = Void
--}
-newtype X = X X
+-- | The empty type, used to close output ends
+type X = Void
 
 -- | Use 'closed' to \"handle\" impossible outputs
 closed :: X -> a
-closed (X x) = closed x
+closed = Data.Void.absurd
 {-# INLINABLE closed #-}
diff --git a/src/Pipes/Lift.hs b/src/Pipes/Lift.hs
--- a/src/Pipes/Lift.hs
+++ b/src/Pipes/Lift.hs
@@ -97,7 +97,7 @@
     :: Monad m
     => Proxy a' a b' b (E.ExceptT e m) r
     -> Proxy a' a b' b m (Either e r)
-runExceptP    = E.runExceptT . distribute 
+runExceptP    = E.runExceptT . distribute
 {-# INLINABLE runExceptP #-}
 
 -- | Catch an error in the base monad
diff --git a/src/Pipes/Prelude.hs b/src/Pipes/Prelude.hs
--- a/src/Pipes/Prelude.hs
+++ b/src/Pipes/Prelude.hs
@@ -45,7 +45,9 @@
     , sequence
     , mapFoldable
     , filter
+    , mapMaybe
     , filterM
+    , wither
     , take
     , takeWhile
     , takeWhile'
@@ -101,7 +103,7 @@
     ) where
 
 import Control.Exception (throwIO, try)
-import Control.Monad (liftM, when, unless)
+import Control.Monad (liftM, when, unless, (>=>))
 import Control.Monad.Trans.State.Strict (get, put)
 import Data.Functor.Identity (Identity, runIdentity)
 import Foreign.C.Error (Errno(Errno), ePIPE)
@@ -182,8 +184,12 @@
 {-| Read 'String's from a 'IO.Handle' using 'IO.hGetLine'
 
     Terminates on end of input
+
+@
+'fromHandle' :: 'MonadIO' m => 'IO.Handle' -> 'Producer' 'String' m ()
+@
 -}
-fromHandle :: MonadIO m => IO.Handle -> Producer' String m ()
+fromHandle :: MonadIO m => IO.Handle -> Proxy x' x () String m ()
 fromHandle h = go
   where
     go = do
@@ -194,8 +200,11 @@
             go
 {-# INLINABLE fromHandle #-}
 
--- | Repeat a monadic action indefinitely, 'yield'ing each result
-repeatM :: Monad m => m a -> Producer' a m r
+{-| Repeat a monadic action indefinitely, 'yield'ing each result
+
+'repeatM' :: 'Monad' m => m a -> 'Producer' a m r
+-}
+repeatM :: Monad m => m a -> Proxy x' x () a m r
 repeatM m = lift m >~ cat
 {-# INLINABLE [1] repeatM #-}
 
@@ -208,8 +217,12 @@
 > replicateM  0      x = return ()
 >
 > replicateM (m + n) x = replicateM m x >> replicateM n x  -- 0 <= {m,n}
+
+@
+'replicateM' :: 'Monad' m => Int -> m a -> 'Producer' a m ()
+@
 -}
-replicateM :: Monad m => Int -> m a -> Producer' a m ()
+replicateM :: Monad m => Int -> m a -> Proxy x' x () a m ()
 replicateM n m = lift m >~ take n
 {-# INLINABLE replicateM #-}
 
@@ -289,7 +302,7 @@
   #-}
 
 -- | 'discard' all incoming values
-drain :: Monad m => Consumer' a m r
+drain :: Functor m => Consumer' a m r
 drain = for cat discard
 {-# INLINABLE [1] drain #-}
 
@@ -317,7 +330,7 @@
 >
 > map (g . f) = map f >-> map g
 -}
-map :: Monad m => (a -> b) -> Pipe a b m r
+map :: Functor m => (a -> b) -> Pipe a b m r
 map f = for cat (\a -> yield (f a))
 {-# INLINABLE [1] map #-}
 
@@ -360,7 +373,7 @@
 {- | Apply a function to all values flowing downstream, and
      forward each element of the result.
 -}
-mapFoldable :: (Monad m, Foldable t) => (a -> t b) -> Pipe a b m r
+mapFoldable :: (Functor m, Foldable t) => (a -> t b) -> Pipe a b m r
 mapFoldable f = for cat (\a -> each (f a))
 {-# INLINABLE [1] mapFoldable #-}
 
@@ -374,8 +387,10 @@
 > filter (pure True) = cat
 >
 > filter (liftA2 (&&) p1 p2) = filter p1 >-> filter p2
+>
+> filter f = mapMaybe (\a -> a <$ guard (f a))
 -}
-filter :: Monad m => (a -> Bool) -> Pipe a a m r
+filter :: Functor m => (a -> Bool) -> Pipe a a m r
 filter predicate = for cat $ \a -> when (predicate a) (yield a)
 {-# INLINABLE [1] filter #-}
 
@@ -384,12 +399,37 @@
         p >-> filter predicate = for p (\a -> when (predicate a) (yield a))
   #-}
 
+{-| @(mapMaybe f)@ yields 'Just' results of 'f'.
+
+Basic laws:
+
+> mapMaybe (f >=> g) = mapMaybe f >-> mapMaybe g
+>
+> mapMaybe (pure @Maybe . f) = mapMaybe (Just . f) = map f
+>
+> mapMaybe (const Nothing) = drain
+
+As a result of the second law,
+
+> mapMaybe return = mapMaybe Just = cat
+-}
+mapMaybe :: Functor m => (a -> Maybe b) -> Pipe a b m r
+mapMaybe f = for cat $ maybe (pure ()) yield . f
+{-# INLINABLE [1] mapMaybe #-}
+
+{-# RULES
+    "p >-> mapMaybe f" forall p f.
+        p >-> mapMaybe f = for p $ maybe (pure ()) yield . f
+  #-}
+
 {-| @(filterM predicate)@ only forwards values that satisfy the monadic
     predicate
 
 > filterM (pure (pure True)) = cat
 >
 > filterM (liftA2 (liftA2 (&&)) p1 p2) = filterM p1 >-> filterM p2
+>
+> filterM f = wither (\a -> (\b -> a <$ guard b) <$> f a)
 -}
 filterM :: Monad m => (a -> m Bool) -> Pipe a a m r
 filterM predicate = for cat $ \a -> do
@@ -404,6 +444,34 @@
             when b (yield a) )
   #-}
 
+{-| @(wither f)@ forwards 'Just' values produced by the
+    monadic action.
+
+Basic laws:
+
+> wither (runMaybeT . (MaybeT . f >=> MaybeT . g)) = wither f >-> wither g
+>
+> wither (runMaybeT . lift . f) = wither (fmap Just . f) = mapM f
+>
+> wither (pure . f) = mapMaybe f
+
+As a result of the second law,
+
+> wither (runMaybeT . return) = cat
+
+As a result of the third law,
+
+> wither (pure . const Nothing) = wither (const (pure Nothing)) = drain
+-}
+wither :: Monad m => (a -> m (Maybe b)) -> Pipe a b m r
+wither f = for cat $ lift . f >=> maybe (pure ()) yield
+{-# INLINABLE [1] wither #-}
+
+{-# RULES
+    "p >-> wither f" forall p f .
+        p >-> wither f = for p $ lift . f >=> maybe (pure ()) yield
+  #-}
+
 {-| @(take n)@ only allows @n@ values to pass through
 
 > take 0 = return ()
@@ -414,7 +482,7 @@
 >
 > take (min m n) = take m >-> take n
 -}
-take :: Monad m => Int -> Pipe a a m ()
+take :: Functor m => Int -> Pipe a a m ()
 take = go
   where
     go 0 = return () 
@@ -431,7 +499,7 @@
 >
 > takeWhile (liftA2 (&&) p1 p2) = takeWhile p1 >-> takeWhile p2
 -}
-takeWhile :: Monad m => (a -> Bool) -> Pipe a a m ()
+takeWhile :: Functor m => (a -> Bool) -> Pipe a a m ()
 takeWhile predicate = go
   where
     go = do
@@ -450,7 +518,7 @@
 >
 > takeWhile' (liftA2 (&&) p1 p2) = takeWhile' p1 >-> takeWhile' p2
 -}
-takeWhile' :: Monad m => (a -> Bool) -> Pipe a a m a
+takeWhile' :: Functor m => (a -> Bool) -> Pipe a a m a
 takeWhile' predicate = go
   where
     go = do
@@ -468,7 +536,7 @@
 >
 > drop (m + n) = drop m >-> drop n
 -}
-drop :: Monad m => Int -> Pipe a a m r
+drop :: Functor m => Int -> Pipe a a m r
 drop = go
   where
     go 0 = cat
@@ -484,7 +552,7 @@
 >
 > dropWhile (liftA2 (||) p1 p2) = dropWhile p1 >-> dropWhile p2
 -}
-dropWhile :: Monad m => (a -> Bool) -> Pipe a a m r
+dropWhile :: Functor m => (a -> Bool) -> Pipe a a m r
 dropWhile predicate = go
   where
     go = do
@@ -497,7 +565,7 @@
 {-# INLINABLE dropWhile #-}
 
 -- | Flatten all 'Foldable' elements flowing downstream
-concat :: (Monad m, Foldable f) => Pipe (f a) a m r
+concat :: (Functor m, Foldable f) => Pipe (f a) a m r
 concat = for cat each
 {-# INLINABLE [1] concat #-}
 
@@ -506,12 +574,12 @@
   #-}
 
 -- | Outputs the indices of all elements that match the given element
-elemIndices :: (Monad m, Eq a) => a -> Pipe a Int m r
+elemIndices :: (Functor m, Eq a) => a -> Pipe a Int m r
 elemIndices a = findIndices (a ==)
 {-# INLINABLE elemIndices #-}
 
 -- | Outputs the indices of all elements that satisfied the predicate
-findIndices :: Monad m => (a -> Bool) -> Pipe a Int m r
+findIndices :: Functor m => (a -> Bool) -> Pipe a Int m r
 findIndices predicate = go 0
   where
     go n = do
@@ -524,7 +592,7 @@
 
 > Control.Foldl.purely scan :: Monad m => Fold a b -> Pipe a b m r
 -}
-scan :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Pipe a b m r
+scan :: Functor m => (x -> a -> x) -> x -> (x -> b) -> Pipe a b m r
 scan step begin done = go begin
   where
     go x = do
@@ -536,7 +604,7 @@
 
 {-| Strict, monadic left scan
 
-> Control.Foldl.impurely scan :: Monad m => FoldM a m b -> Pipe a b m r
+> Control.Foldl.impurely scanM :: Monad m => FoldM m a b -> Pipe a b m r
 -}
 scanM :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> Pipe a b m r
 scanM step begin done = do
@@ -576,7 +644,7 @@
   #-}
 
 -- | Parse 'Read'able values, only forwarding the value if the parse succeeds
-read :: (Monad m, Read a) => Pipe String a m r
+read :: (Functor m, Read a) => Pipe String a m r
 read = for cat $ \str -> case (reads str) of
     [(a, "")] -> yield a
     _         -> return ()
@@ -590,12 +658,12 @@
   #-}
 
 -- | Convert 'Show'able values to 'String's
-show :: (Monad m, Show a) => Pipe a String m r
+show :: (Functor m, Show a) => Pipe a String m r
 show = map Prelude.show
 {-# INLINABLE show #-}
 
 -- | Evaluate all values flowing downstream to WHNF
-seq :: Monad m => Pipe a a m r
+seq :: Functor m => Pipe a a m r
 seq = for cat $ \a -> yield $! a
 {-# INLINABLE seq #-}
 
@@ -613,7 +681,7 @@
     Use these to fold the output of a 'Producer'.  Many of these folds will stop
     drawing elements if they can compute their result early, like 'any':
 
->>> P.any null P.stdinLn
+>>> P.any Prelude.null P.stdinLn
 Test<Enter>
 ABC<Enter>
 <Enter>
@@ -857,9 +925,9 @@
 
 -- | Zip two 'Producer's
 zip :: Monad m
-    => (Producer   a     m r)
-    -> (Producer      b  m r)
-    -> (Producer' (a, b) m r)
+    => (Producer       a     m r)
+    -> (Producer          b  m r)
+    -> (Proxy x' x () (a, b) m r)
 zip = zipWith (,)
 {-# INLINABLE zip #-}
 
@@ -868,7 +936,7 @@
     => (a -> b -> c)
     -> (Producer  a m r)
     -> (Producer  b m r)
-    -> (Producer' c m r)
+    -> (Proxy x' x () c m r)
 zipWith f = go
   where
     go p1 p2 = do
diff --git a/src/Pipes/Tutorial.hs b/src/Pipes/Tutorial.hs
--- a/src/Pipes/Tutorial.hs
+++ b/src/Pipes/Tutorial.hs
@@ -750,7 +750,7 @@
 
     A 'Pipe' is a monad transformer that is a mix between a 'Producer' and
     'Consumer', because a 'Pipe' can both 'await' and 'yield'.  The following
-    example 'Pipe' is analagous to the Prelude's 'take', only allowing a fixed
+    example 'Pipe' is analogous to the Prelude's 'take', only allowing a fixed
     number of values to flow through:
 
 > -- take.hs
