diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -255,7 +255,7 @@
 
 Rather than wrapping each step in a monadic 'layer', such a layer is put alongside separate 'pure' constructors for a functor 'layer' and a final return value. The maneuver is very friendly to the compiler, but requires a bit of subtlety to protect a sound monad instance. Just such an optimization is adopted internally by the `pipes` library. As in `pipes`, the constructors are here left in an `Internal` module; the main `Streaming` module exporting the type itself and various operations and instances.
 
-I ran a simple [benchmark](https://gist.github.com/michaelt/ee3710c5bab9b7d0892bd552e0eedfd9) (adjusting a [script](https://github.com/jwiegley/streaming-tests) of John Weigly) using a very simple composition of functions:
+I ran a simple [benchmark](https://gist.github.com/michaelt/ee3710c5bab9b7d0892bd552e0eedfd9) (adjusting a [script](https://github.com/jwiegley/streaming-tests) of John Wiegley) using a very simple composition of functions:
 
     toList 
     . filter (\x -> x `mod` 2 == 0) 
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,6 +1,23 @@
-- ???
+- 0.2.3.0
+    Add `wrapEffect`.
 
-    Added `nubOrd`, `nubInt`, `nubOrdOn`, `nubIntOn`.
+    Compatibility with base 4.13.
+    
+    Provide a MonadFail instance for Stream.
+
+    Only depend on `semigroups` on old GHCs.
+
+    Add `untilLeft` (counterpart to `untilRight`)
+
+    Add doctests.
+
+    Enable -Wall in cabal file.
+
+    Build with ghc >= 7.10.3.
+
+- 0.2.2.0
+
+    Add `nubOrd`, `nubInt`, `nubOrdOn`, `nubIntOn`.
 
     Fix performance regression in `for`.
     
diff --git a/src/Data/Functor/Of.hs b/src/Data/Functor/Of.hs
--- a/src/Data/Functor/Of.hs
+++ b/src/Data/Functor/Of.hs
@@ -1,18 +1,19 @@
 {-# LANGUAGE CPP, DeriveDataTypeable, DeriveTraversable, DeriveFoldable,
        DeriveGeneric #-}
-module Data.Functor.Of where
+module Data.Functor.Of (Of(..)) where
 import Data.Monoid (Monoid (..))
 import Data.Semigroup (Semigroup (..))
 import Control.Applicative
 import Data.Traversable (Traversable)
 import Data.Foldable (Foldable)
-#if MIN_VERSION_base(4,8,0)
 import Data.Bifunctor
-#endif
 import Data.Data
-import Data.Typeable
-import GHC.Generics (Generic, Generic1)
+#if MIN_VERSION_base(4,9,0)
 import Data.Functor.Classes
+import Data.Foldable (Foldable)
+import Data.Traversable (Traversable)
+#endif
+import GHC.Generics (Generic, Generic1)
 
 -- | A left-strict pair; the base functor for streams of individual elements.
 data Of a b = !a :> b
@@ -35,7 +36,7 @@
 instance Functor (Of a) where
   fmap f (a :> x) = a :> f x
   {-#INLINE fmap #-}
-  a <$ (b :> x)   = b :> a
+  a <$ (b :> _)   = b :> a
   {-#INLINE (<$) #-}
 
 #if MIN_VERSION_base(4,8,0)
@@ -51,24 +52,31 @@
 instance Monoid a => Applicative (Of a) where
   pure x = mempty :> x
   {-#INLINE pure #-}
-  m :> f <*> m' :> x = mappend m m' :> f x
+  (m :> f) <*> (m' :> x) = mappend m m' :> f x
   {-#INLINE (<*>) #-}
-  m :> x *> m' :> y  = mappend m m' :> y
+  (m :> _) *> (m' :> y)  = mappend m m' :> y
   {-#INLINE (*>) #-}
-  m :> x <* m' :> y  = mappend m m' :> x
+  (m :> x) <* (m' :> _)  = mappend m m' :> x
   {-#INLINE (<*) #-}
 
 instance Monoid a => Monad (Of a) where
-  return x = mempty :> x
+  return = pure
   {-#INLINE return #-}
-  m :> x >> m' :> y = mappend m m' :> y
+  (m :> _) >> (m' :> y) = mappend m m' :> y
   {-#INLINE (>>) #-}
-  m :> x >>= f = let m' :> y = f x in mappend m m' :> y
+  (m :> x) >>= f = let m' :> y = f x in mappend m m' :> y
   {-#INLINE (>>=) #-}
 
+#if MIN_VERSION_base(4,9,0)
 instance Show a => Show1 (Of a) where
   liftShowsPrec = liftShowsPrec2 showsPrec showList
 
+instance Eq a => Eq1 (Of a) where
+  liftEq = liftEq2 (==)
+
+instance Ord a => Ord1 (Of a) where
+  liftCompare = liftCompare2 compare
+
 instance Show2 Of where
   liftShowsPrec2 spa _sla spb _slb p (a :> b) =
     showParen (p > 5) $
@@ -76,15 +84,11 @@
     showString " :> " .
     spb 6 b
 
-instance Eq a => Eq1 (Of a) where
-  liftEq = liftEq2 (==)
-
-instance Ord a => Ord1 (Of a) where
-  liftCompare = liftCompare2 compare
-
 instance Eq2 Of where
-  liftEq2 eq1 eq2 (x :> y) (z :> w) = eq1 x z && eq2 y w
+  liftEq2 f g (x :> y) (z :> w) = f x z && g y w
 
 instance Ord2 Of where
   liftCompare2 comp1 comp2 (x :> y) (z :> w) =
     comp1 x z `mappend` comp2 y w
+#endif
+
diff --git a/src/Streaming.hs b/src/Streaming.hs
--- a/src/Streaming.hs
+++ b/src/Streaming.hs
@@ -1,6 +1,5 @@
 {-# LANGUAGE RankNTypes #-}
 
-{-# OPTIONS_GHC -Wall #-}
 module Streaming
    (
    -- * An iterable streaming monad transformer
@@ -115,10 +114,10 @@
     Some of these are quite abstract and pervade any use of the library,
     e.g.
 
->   maps ::    (forall x . f x -> g x)     -> Stream f m r -> Stream g m r
->   mapped ::  (forall x . f x -> m (g x)) -> Stream f m r -> Stream g m r
->   hoist ::   (forall x . m x -> n x)     -> Stream f m r -> Stream f n r -- from the MFunctor instance
->   concats :: Stream (Stream f m) m r -> Stream f m r   
+>   maps    :: (forall x . f x -> g x)     -> Stream f m r -> Stream g m r
+>   mapped  :: (forall x . f x -> m (g x)) -> Stream f m r -> Stream g m r
+>   hoist   :: (forall x . m x -> n x)     -> Stream f m r -> Stream f n r -- from the MFunctor instance
+>   concats :: Stream (Stream f m) m r     -> Stream f m r
 
     (assuming here and thoughout that @m@ or @n@ satisfies a @Monad@ constraint, and
     @f@ or @g@ a @Functor@ constraint.)
@@ -128,12 +127,12 @@
 >   chunksOf     :: Int -> Stream f m r -> Stream (Stream f m) m r
 >   splitsAt     :: Int -> Stream f m r -> Stream f m (Stream f m r)
 >   zipsWith     :: (forall x y. f x -> g y -> h (x, y))
-                 -> Stream f m r -> Stream g m r -> Stream h m r
+>                -> Stream f m r -> Stream g m r -> Stream h m r
 >   zipsWith'    :: (forall x y p. (x -> y -> p) -> f x -> g y -> h p)
-                 -> Stream f m r -> Stream g m r -> Stream h m r
+>                -> Stream f m r -> Stream g m r -> Stream h m r
 >   intercalates :: Stream f m () -> Stream (Stream f m) m r -> Stream f m r
 >   unzips       :: Stream (Compose f g) m r ->  Stream f (Stream g m) r
->   separate     :: Stream (Sum f g) m r -> Stream f (Stream g) m r  -- cp. partitionEithers
+>   separate     :: Stream (Sum f g) m r -> Stream f (Stream g m) r  -- cp. partitionEithers
 >   unseparate   :: Stream f (Stream g) m r -> Stream (Sum f g) m r
 >   groups       :: Stream (Sum f g) m r -> Stream (Sum (Stream f m) (Stream g m)) m r
 
@@ -168,5 +167,3 @@
 > concats :: (Monad m, MonadTrans t, Monad (t m)) => Stream (t m) m a -> t m a
 > concats stream = destroy stream join (join . lift) return
 -}
-
-
diff --git a/src/Streaming/Internal.hs b/src/Streaming/Internal.hs
--- a/src/Streaming/Internal.hs
+++ b/src/Streaming/Internal.hs
@@ -1,20 +1,17 @@
-{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE GADTs #-}
+{-# LANGUAGE BangPatterns          #-}
+{-# LANGUAGE CPP                   #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE GADTs                 #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving #-}
-{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE RankNTypes            #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE UndecidableInstances  #-}
 
-{-# OPTIONS_GHC -Wall #-}
 module Streaming.Internal (
     -- * The free monad transformer
     -- $stream
     Stream (..)
-  
+
     -- * Introducing a stream
     , unfold
     , replicates
@@ -28,7 +25,7 @@
     , delays
     , never
     , untilJust
-  
+
     -- * Eliminating a stream
     , intercalates
     , concats
@@ -36,10 +33,10 @@
     , iterTM
     , destroy
     , streamFold
-  
+
     -- * Inspecting a stream wrap by wrap
     , inspect
-  
+
     -- * Transforming streams
     , maps
     , mapsM
@@ -52,7 +49,7 @@
     , distribute
     , groups
 --    , groupInL
-  
+
     -- *  Splitting streams
     , chunksOf
     , splitsAt
@@ -60,7 +57,7 @@
     , cutoff
     -- , period
     -- , periods
-  
+
     -- * Zipping and unzipping streams
     , zipsWith
     , zipsWith'
@@ -72,10 +69,10 @@
     , expand
     , expandPost
 
-  
+
     -- * Assorted Data.Functor.x help
     , switch
-  
+
     -- *  For use in implementation
     , unexposed
     , hoistExposed
@@ -83,25 +80,29 @@
     , mapsExposed
     , mapsMExposed
     , destroyExposed
-  
+
    ) where
 
+import Control.Applicative
+import Control.Concurrent (threadDelay)
 import Control.Monad
-import Control.Monad.Trans
-import Control.Monad.Reader.Class
-import Control.Monad.State.Class
 import Control.Monad.Error.Class
-import Control.Applicative
-import Data.Function ( on )
+import Control.Monad.Fail as Fail
 import Control.Monad.Morph
-import Data.Monoid (Monoid (..))
-import Data.Semigroup (Semigroup (..))
+import Control.Monad.Reader.Class
+import Control.Monad.State.Class
+import Control.Monad.Trans
 import Data.Data (Typeable)
-import Prelude hiding (splitAt)
+import Data.Function ( on )
+import Data.Functor.Classes
 import Data.Functor.Compose
 import Data.Functor.Sum
-import Data.Functor.Classes
-import Control.Concurrent (threadDelay)
+import Data.Monoid (Monoid (..))
+import Data.Semigroup (Semigroup (..))
+
+-- $setup
+-- >>> import Streaming.Prelude as S
+
 {- $stream
 
     The 'Stream' data type is equivalent to @FreeT@ and can represent any effectful
@@ -157,6 +158,8 @@
   (<=) = (<=) `on` inspect
   (>=) = (>=) `on` inspect
 
+#if MIN_VERSION_base(4,9,0)
+
 -- We could avoid a Show1 constraint for our Show1 instance by sneakily
 -- mapping everything to a single known type, but there's really no way
 -- to do that for Eq1 or Ord1.
@@ -165,7 +168,7 @@
     where
       liftEqExposed (Return x) (Return y) = eq x y
       liftEqExposed (Effect m) (Effect n) = liftEq liftEqExposed m n
-      liftEqExposed (Step f) (Step g) = liftEq liftEqExposed f g
+      liftEqExposed (Step f)   (Step g)   = liftEq liftEqExposed f g
       liftEqExposed _ _ = False
 
 instance (Monad m, Functor f, Ord1 m, Ord1 f) => Ord1 (Stream f m) where
@@ -173,11 +176,13 @@
     where
       liftCmpExposed (Return x) (Return y) = cmp x y
       liftCmpExposed (Effect m) (Effect n) = liftCompare liftCmpExposed m n
-      liftCmpExposed (Step f) (Step g) = liftCompare liftCmpExposed f g
+      liftCmpExposed (Step f)   (Step g)   = liftCompare liftCmpExposed f g
       liftCmpExposed (Return _) _ = LT
       liftCmpExposed _ (Return _) = GT
       liftCmpExposed _ _ = error "liftCmpExposed: stream was exposed!"
 
+#endif
+
 -- We could get a much less scary implementation using Show1, but
 -- Show1 instances aren't nearly as common as Show instances.
 --
@@ -196,9 +201,11 @@
     flip fmap (inspect xs) $ \front ->
       SS $ \d -> showParen (d > 10) $
         case front of
-          Left r ->  showString "Return " . showsPrec 11 r
+          Left  r -> showString "Return " . showsPrec 11 r
           Right f -> showString "Step "   . showsPrec 11 f)
 
+#if MIN_VERSION_base(4,9,0)
+
 instance (Monad m, Functor f, Show (m ShowSWrapper), Show (f ShowSWrapper))
          => Show1 (Stream f m) where
   liftShowsPrec sp sl p xs = showParen (p > 10) $
@@ -206,47 +213,62 @@
     flip fmap (inspect xs) $ \front ->
       SS $ \d -> showParen (d > 10) $
         case front of
-          Left r ->  showString "Return " . sp 11 r
+          Left  r -> showString "Return " . sp 11 r
           Right f -> showString "Step "   .
                      showsPrec 11 (fmap (SS . (\str i -> liftShowsPrec sp sl i str)) f))
 
+#endif
+
 newtype ShowSWrapper = SS (Int -> ShowS)
 instance Show ShowSWrapper where
   showsPrec p (SS s) = s p
 
+-- | Operates covariantly on the stream result, not on its elements:
+--
+-- @
+-- Stream (Of a) m r
+--            ^    ^
+--            |    `--- This is what `Functor` and `Applicative` use
+--            `--- This is what functions like S.map/S.zipWith use
+-- @
 instance (Functor f, Monad m) => Functor (Stream f m) where
   fmap f = loop where
     loop stream = case stream of
       Return r -> Return (f r)
-      Effect m  -> Effect (do {stream' <- m; return (loop stream')})
-      Step g -> Step (fmap loop g)
+      Effect m -> Effect (do {stream' <- m; return (loop stream')})
+      Step   g -> Step (fmap loop g)
   {-# INLINABLE fmap #-}
   a <$ stream0 = loop stream0 where
     loop stream = case stream of
       Return _ -> Return a
       Effect m -> Effect (do {stream' <- m; return (loop stream')})
-      Step f -> Step (fmap loop f)
-  {-# INLINABLE (<$) #-}  
+      Step   f -> Step (fmap loop f)
+  {-# INLINABLE (<$) #-}
 
 instance (Functor f, Monad m) => Monad (Stream f m) where
-  return = Return
+  return = pure
   {-# INLINE return #-}
   (>>) = (*>)
   {-# INLINE (>>) #-}
   -- (>>=) = _bind
-  -- {-#INLINE (>>=) #-}
+  -- {-# INLINE (>>=) #-}
   --
   stream >>= f =
     loop stream where
     loop stream0 = case stream0 of
       Step fstr -> Step (fmap loop fstr)
-      Effect m   -> Effect (fmap loop m)
+      Effect m  -> Effect (fmap loop m)
       Return r  -> f r
-  {-# INLINABLE (>>=) #-}       
+  {-# INLINABLE (>>=) #-}
 
-  fail = lift . fail
-  {-#INLINE fail #-}
+#if !(MIN_VERSION_base(4,13,0))
+  fail = lift . Prelude.fail
+  {-# INLINE fail #-}
+#endif
 
+instance (Functor f, MonadFail m) => MonadFail (Stream f m) where
+  fail = lift . Fail.fail
+  {-# INLINE fail #-}
 
 -- _bind
 --     :: (Functor f, Monad m)
@@ -258,7 +280,7 @@
 --       Step fstr  -> Step (fmap go fstr)
 --       Effect m   -> Effect (m >>= \s -> return (go s))
 --       Return r  -> f r
--- {-#INLINABLE _bind #-}
+-- {-# INLINABLE _bind #-}
 --
 -- see https://github.com/Gabriel439/Haskell-Pipes-Library/pull/163
 -- for a plan to delay inlining and manage interaction with other operations.
@@ -275,12 +297,12 @@
 instance (Functor f, Monad m) => Applicative (Stream f m) where
   pure = Return
   {-# INLINE pure #-}
-  streamf <*> streamx = do {f <- streamf; x <- streamx; return (f x)} 
-  {-# INLINE (<*>) #-}  
+  streamf <*> streamx = do {f <- streamf; x <- streamx; return (f x)}
+  {-# INLINE (<*>) #-}
   stream1 *> stream2 = loop stream1 where
     loop stream = case stream of
       Return _ -> stream2
-      Effect m  -> Effect (fmap loop m)
+      Effect m -> Effect (fmap loop m)
       Step f   -> Step (fmap loop f)
   {-# INLINABLE (*>) #-}
 
@@ -294,21 +316,21 @@
 -}
 instance (Applicative f, Monad m) => Alternative (Stream f m) where
   empty = never
-  {-#INLINE empty #-}
+  {-# INLINE empty #-}
 
   str <|> str' = zipsWith' liftA2 str str'
-  {-#INLINE (<|>) #-}
+  {-# INLINE (<|>) #-}
 
 instance (Functor f, Monad m, Semigroup w) => Semigroup (Stream f m w) where
   a <> b = a >>= \w -> fmap (w <>) b
-  {-#INLINE (<>) #-}
+  {-# INLINE (<>) #-}
 
 instance (Functor f, Monad m, Monoid w) => Monoid (Stream f m w) where
   mempty = return mempty
-  {-#INLINE mempty #-}
+  {-# INLINE mempty #-}
 #if !(MIN_VERSION_base(4,11,0))
   mappend a b = a >>= \w -> fmap (w `mappend`) b
-  {-#INLINE mappend #-}
+  {-# INLINE mappend #-}
 #endif
 
 instance (Applicative f, Monad m) => MonadPlus (Stream f m) where
@@ -322,17 +344,17 @@
 instance Functor f => MFunctor (Stream f) where
   hoist trans = loop  where
     loop stream = case stream of
-      Return r  -> Return r
-      Effect m   -> Effect (trans (fmap loop m))
-      Step f    -> Step (fmap loop f)
-  {-# INLINABLE hoist #-}  
+      Return r -> Return r
+      Effect m -> Effect (trans (fmap loop m))
+      Step f   -> Step (fmap loop f)
+  {-# INLINABLE hoist #-}
 
 
 instance Functor f => MMonad (Stream f) where
   embed phi = loop where
     loop stream = case stream of
       Return r -> Return r
-      Effect  m -> phi m >>= loop
+      Effect m -> phi m >>= loop
       Step   f -> Step (fmap loop f)
   {-# INLINABLE embed #-}
 
@@ -345,7 +367,7 @@
   {-# INLINE ask #-}
   local f = hoist (local f)
   {-# INLINE local #-}
- 
+
 instance (Functor f, MonadState s m) => MonadState s (Stream f m) where
   get = lift get
   {-# INLINE get #-}
@@ -363,7 +385,7 @@
     loop x = case x of
       Return r -> Return r
       Effect m -> Effect $ fmap loop m `catchError` (return . f)
-      Step g -> Step (fmap loop g)
+      Step   g -> Step (fmap loop g)
   {-# INLINABLE catchError #-}
 
 {-| Map a stream to its church encoding; compare @Data.List.foldr@.
@@ -382,7 +404,7 @@
   loop stream = case stream of
     Return r -> return (done r)
     Effect m -> m >>= loop
-    Step fs -> return (construct (fmap (theEffect . loop) fs))
+    Step fs  -> return (construct (fmap (theEffect . loop) fs))
 {-# INLINABLE destroy #-}
 
 
@@ -421,11 +443,11 @@
   :: (Functor f, Monad m) =>
      (r -> b) -> (m b -> b) ->  (f b -> b) -> Stream f m r -> b
 streamFold done theEffect construct stream  = destroy stream construct theEffect done
-{-#INLINE streamFold #-}
+{-# INLINE streamFold #-}
 
 {- | Reflect a church-encoded stream; cp. @GHC.Exts.build@
 
-> streamFold return_ effect_ step_ (streamBuild psi)  = psi return_ effect_ step_
+> streamFold return_ effect_ step_ (streamBuild psi) = psi return_ effect_ step_
 -}
 streamBuild
   :: (forall b . (r -> b) -> (m b -> b) -> (f b -> b) ->  b) ->  Stream f m r
@@ -445,10 +467,10 @@
 inspect = loop where
   loop stream = case stream of
     Return r -> return (Left r)
-    Effect m  -> m >>= loop
+    Effect m -> m >>= loop
     Step fs  -> return (Right fs)
 {-# INLINABLE inspect #-}
-  
+
 {-| Build a @Stream@ by unfolding steps starting from a seed. See also
     the specialized 'Streaming.Prelude.unfoldr' in the prelude.
 
@@ -463,9 +485,9 @@
 unfold step = loop where
   loop s0 = Effect $ do
     e <- step s0
-    case e of
-      Left r -> return (Return r)
-      Right fs -> return (Step (fmap loop fs))
+    return $ case e of
+       Left  r  -> Return r
+       Right fs -> Step (fmap loop fs)
 {-# INLINABLE unfold #-}
 
 
@@ -480,9 +502,9 @@
      => (forall x . f x -> g x) -> Stream f m r -> Stream g m r
 maps phi = loop where
   loop stream = case stream of
-    Return r  -> Return r
-    Effect m   -> Effect (fmap loop m)
-    Step f    -> Step (phi (fmap loop f))
+    Return r -> Return r
+    Effect m -> Effect (fmap loop m)
+    Step   f -> Step (phi (fmap loop f))
 {-# INLINABLE maps #-}
 
 
@@ -499,9 +521,9 @@
 mapsM :: (Monad m, Functor f) => (forall x . f x -> m (g x)) -> Stream f m r -> Stream g m r
 mapsM phi = loop where
   loop stream = case stream of
-    Return r  -> Return r
-    Effect m   -> Effect (fmap loop m)
-    Step f    -> Effect (fmap Step (phi (fmap loop f)))
+    Return r -> Return r
+    Effect m -> Effect (fmap loop m)
+    Step   f -> Effect (fmap Step (phi (fmap loop f)))
 {-# INLINABLE mapsM #-}
 
 {- | Map layers of one functor to another with a transformation. Compare
@@ -509,8 +531,7 @@
 
 > mapsPost id = id
 > mapsPost f . mapsPost g = mapsPost (f . g)
-> mapsPost f = mapsPost f
-
+> mapsPost f = maps f
 
      @mapsPost@ is essentially the same as 'maps', but it imposes a 'Functor' constraint on
      its target functor rather than its source functor. It should be preferred if 'fmap'
@@ -524,7 +545,7 @@
   loop stream = case stream of
     Return r -> Return r
     Effect m -> Effect (fmap loop m)
-    Step f -> Step $ fmap loop $ phi f
+    Step   f -> Step $ fmap loop $ phi f
 {-# INLINABLE mapsPost #-}
 
 {- | Map layers of one functor to another with a transformation involving the base monad.
@@ -549,7 +570,7 @@
   loop stream = case stream of
     Return r -> Return r
     Effect m -> Effect (fmap loop m)
-    Step f -> Effect $ fmap (Step . fmap loop) (phi f)
+    Step   f -> Effect $ fmap (Step . fmap loop) (phi f)
 {-# INLINABLE mapsMPost #-}
 
 {-| Rearrange a succession of layers of the form @Compose m (f x)@.
@@ -573,7 +594,7 @@
 decompose = loop where
   loop stream = case stream of
     Return r -> Return r
-    Effect m ->  Effect (fmap loop m)
+    Effect m -> Effect (fmap loop m)
     Step (Compose mstr) -> Effect $ do
       str <- mstr
       return (Step (fmap loop str))
@@ -584,8 +605,8 @@
 run :: Monad m => Stream m m r -> m r
 run = loop where
   loop stream = case stream of
-    Return r -> return r
-    Effect  m -> m >>= loop
+    Return r   -> return r
+    Effect  m  -> m >>= loop
     Step mrest -> mrest >>= loop
 {-# INLINABLE run #-}
 
@@ -606,16 +627,16 @@
 intercalates sep = go0
   where
     go0 f = case f of
-      Return r -> return r
-      Effect m -> lift m >>= go0
+      Return r  -> return r
+      Effect m  -> lift m >>= go0
       Step fstr -> do
         f' <- fstr
         go1 f'
     go1 f = case f of
-      Return r -> return r
-      Effect m     -> lift m >>= go1
+      Return r  -> return r
+      Effect m  -> lift m >>= go1
       Step fstr ->  do
-        _ <- sep
+        _  <- sep
         f' <- fstr
         go1 f'
 {-# INLINABLE intercalates #-}
@@ -649,7 +670,7 @@
 concats  = loop where
   loop stream = case stream of
     Return r -> return r
-    Effect m  -> lift m >>= loop
+    Effect m -> lift m >>= loop
     Step fs  -> fs >>= loop
 {-# INLINE concats #-}
 
@@ -679,11 +700,11 @@
 splitsAt :: (Monad m, Functor f) => Int -> Stream f m r -> Stream f m (Stream f m r)
 splitsAt  = loop  where
   loop !n stream
-    | n <= 0 = Return stream
+    | n <= 0    = Return stream
     | otherwise = case stream of
-        Return r       -> Return (Return r)
-        Effect m        -> Effect (fmap (loop n) m)
-        Step fs        -> case n of
+        Return r -> Return (Return r)
+        Effect m -> Effect (fmap (loop n) m)
+        Step fs  -> case n of
           0 -> Return (Step fs)
           _ -> Step (fmap (loop (n-1)) fs)
 {-# INLINABLE splitsAt #-}
@@ -716,7 +737,7 @@
 -}
 takes :: (Monad m, Functor f) => Int -> Stream f m r -> Stream f m ()
 takes n = void . splitsAt n
-{-# INLINE takes #-}                      
+{-# INLINE takes #-}
 
 {-| Break a stream into substreams each with n functorial layers.
 
@@ -731,7 +752,7 @@
     Return r  -> Return r
     Effect m  -> Effect (fmap loop m)
     Step fs   -> Step (Step (fmap (fmap loop . splitsAt (n0-1)) fs))
-{-# INLINABLE chunksOf #-}        
+{-# INLINABLE chunksOf #-}
 
 {- | Make it possible to \'run\' the underlying transformed monad.
 -}
@@ -742,19 +763,19 @@
     Return r     -> lift (Return r)
     Effect tmstr -> hoist lift tmstr >>= loop
     Step fstr    -> join (lift (Step (fmap (Return . loop) fstr)))
-{-#INLINABLE distribute #-}
-  
+{-# INLINABLE distribute #-}
+
 -- | Repeat a functorial layer (a \"command\" or \"instruction\") forever.
 repeats :: (Monad m, Functor f) => f () -> Stream f m r
 repeats f = loop where
-  loop = Effect (return (Step (fmap (\_ -> loop) f)))
+  loop = Effect (return (Step (loop <$ f)))
 
 -- | Repeat an effect containing a functorial layer, command or instruction forever.
 repeatsM :: (Monad m, Functor f) => m (f ()) -> Stream f m r
 repeatsM mf = loop where
   loop = Effect $ do
      f <- mf
-     return $ Step $ fmap (\_ -> loop) f
+     return $ Step $ loop <$ f
 
 {- | Repeat a functorial layer, command or instruction a fixed number of times.
 
@@ -788,7 +809,7 @@
 inspectC :: Monad m => (r -> m a) -> (f (Stream f m r) -> m a) -> Stream f m r -> m a
 inspectC f g = loop where
   loop (Return r) = f r
-  loop (Step x) = g x
+  loop (Step x)   = g x
   loop (Effect m) = m >>= loop
 {-# INLINE inspectC #-}
 
@@ -798,9 +819,9 @@
 hoistExposed :: (Functor m, Functor f) => (forall b. m b -> n b) -> Stream f m a -> Stream f n a
 hoistExposed trans = loop where
   loop stream = case stream of
-    Return r  -> Return r
-    Effect m   -> Effect (trans (fmap loop m))
-    Step f    -> Step (fmap loop f)
+    Return r -> Return r
+    Effect m -> Effect (trans (fmap loop m))
+    Step f   -> Step (fmap loop f)
 {-# INLINABLE hoistExposed #-}
 
 -- | The same as 'hoistExposed', but with a 'Functor' constraint on
@@ -811,7 +832,7 @@
   loop stream = case stream of
     Return r -> Return r
     Effect m -> Effect (fmap loop (trans m))
-    Step f -> Step (fmap loop f)
+    Step   f -> Step (fmap loop f)
 {-# INLINABLE hoistExposedPost #-}
 
 {-# DEPRECATED mapsExposed "Use maps instead." #-}
@@ -844,7 +865,7 @@
 destroyExposed stream0 construct theEffect done = loop stream0 where
   loop stream = case stream of
     Return r -> done r
-    Effect m  -> theEffect (fmap loop m)
+    Effect m -> theEffect (fmap loop m)
     Step fs  -> construct (fmap loop fs)
 {-# INLINABLE destroyExposed #-}
 
@@ -858,9 +879,9 @@
 unexposed = Effect . loop where
   loop stream = case stream of
     Return r -> return (Return r)
-    Effect  m -> m >>= loop
+    Effect m -> m >>= loop
     Step   f -> return (Step (fmap (Effect . loop) f))
-{-# INLINABLE unexposed #-} 
+{-# INLINABLE unexposed #-}
 
 
 {-| Wrap a new layer of a stream. So, e.g.
@@ -889,7 +910,7 @@
 -}
 wrap :: (Monad m, Functor f ) => f (Stream f m r) -> Stream f m r
 wrap = Step
-{-#INLINE wrap #-}
+{-# INLINE wrap #-}
 
 
 {- | Wrap an effect that returns a stream
@@ -899,7 +920,7 @@
 -}
 effect :: (Monad m, Functor f ) => m (Stream f m r) -> Stream f m r
 effect = Effect
-{-#INLINE effect #-}
+{-# INLINE effect #-}
 
 
 {-| @yields@ is like @lift@ for items in the streamed functor.
@@ -916,7 +937,7 @@
 
 yields ::  (Monad m, Functor f) => f r -> Stream f m r
 yields fr = Step (fmap Return fr)
-{-#INLINE yields #-}
+{-# INLINE yields #-}
 
 {-
 Note that if the first stream produces Return, we don't inspect
@@ -966,9 +987,9 @@
     loop :: Stream f m r -> Stream g m r -> Stream h m r
     loop s t = case s of
        Return r -> Return r
-       Step fs -> case t of
+       Step fs  -> case t of
          Return r -> Return r
-         Step gs -> Step $ phi loop fs gs
+         Step gs  -> Step $ phi loop fs gs
          Effect n -> Effect $ fmap (loop s) n
        Effect m -> Effect $ fmap (flip loop t) m
 {-# INLINABLE zipsWith' #-}
@@ -977,7 +998,7 @@
      => Stream f m r -> Stream g m r -> Stream (Compose f g) m r
 zips = zipsWith' go where
   go p fx gy = Compose (fmap (\x -> fmap (\y -> p x y) gy) fx)
-{-# INLINE zips #-} 
+{-# INLINE zips #-}
 
 
 
@@ -998,7 +1019,7 @@
   :: (Monad m, Applicative h) =>
      Stream h m r -> Stream h m r -> Stream h m r
 interleaves = zipsWith' liftA2
-{-# INLINE interleaves #-} 
+{-# INLINE interleaves #-}
 
 
 {-| Swap the order of functors in a sum of functors.
@@ -1016,7 +1037,7 @@
 -}
 switch :: Sum f g r -> Sum g f r
 switch s = case s of InL a -> InR a; InR a -> InL a
-{-#INLINE switch #-}
+{-# INLINE switch #-}
 
 
 
@@ -1033,13 +1054,13 @@
 
     Now, for example, it is convenient to fold on the left and right values separately:
 
->>>  S.toList $ S.toList $ separate odd_even
+>>> S.toList $ S.toList $ separate odd_even
 [2,4,6,8,10] :> ([1,3,5,7,9] :> ())
 
 
    Or we can write them to separate files or whatever:
 
->>> runResourceT $ S.writeFile "even.txt" . S.show $ S.writeFile "odd.txt" . S.show $ S.separate odd_even
+>>> S.writeFile "even.txt" . S.show $ S.writeFile "odd.txt" . S.show $ S.separate odd_even
 >>> :! cat even.txt
 2
 4
@@ -1070,7 +1091,7 @@
   (\x -> case x of InL fss -> wrap fss; InR gss -> effect (yields gss))
   (effect . lift)
   return
-{-#INLINABLE separate #-}
+{-# INLINABLE separate #-}
 
 
 
@@ -1080,7 +1101,7 @@
   (wrap . InL)
   (join . maps InR)
   return
-{-#INLINABLE unseparate #-}
+{-# INLINABLE unseparate #-}
 
 -- | If 'Of' had a @Comonad@ instance, then we'd have
 --
@@ -1093,7 +1114,7 @@
        -> Stream f m r -> Stream g (Stream h m) r
 expand ext = loop where
   loop (Return r) = Return r
-  loop (Step f) = Effect $ Step $ ext (Return . Step) (fmap loop f)
+  loop (Step f)   = Effect $ Step $ ext (Return . Step) (fmap loop f)
   loop (Effect m) = Effect $ Effect $ fmap (Return . loop) m
 {-# INLINABLE expand #-}
 
@@ -1108,7 +1129,7 @@
        -> Stream f m r -> Stream g (Stream h m) r
 expandPost ext = loop where
   loop (Return r) = Return r
-  loop (Step f) = Effect $ Step $ ext (Return . Step . fmap loop) f
+  loop (Step f)   = Effect $ Step $ ext (Return . Step . fmap loop) f
   loop (Effect m) = Effect $ Effect $ fmap (Return . loop) m
 {-# INLINABLE expandPost #-}
 
@@ -1119,7 +1140,7 @@
   (\(Compose fgstr) -> Step (fmap (Effect . yields) fgstr))
   (Effect . lift)
   return
-{-#INLINABLE unzips #-}
+{-# INLINABLE unzips #-}
 
 {-| Group layers in an alternating stream into adjoining sub-streams
     of one type or another.
@@ -1156,8 +1177,8 @@
       Left r           -> return (return r)
       Right (InL fstr) -> return (wrap (InL fstr))
       Right (InR gstr) -> wrap (fmap go gstr)
-{-#INLINABLE groups #-}
-    
+{-# INLINABLE groups #-}
+
 -- groupInL :: (Monad m, Functor f, Functor g)
 --                      => Stream (Sum f g) m r
 --                      -> Stream (Sum (Stream f m) g) m r
@@ -1249,14 +1270,14 @@
 -- The Monad m constraint should really be an Applicative one,
 -- but we still support old versions of base.
 never =  let loop = Step $ pure (Effect (return loop)) in loop
-{-#INLINABLE never #-}
+{-# INLINABLE never #-}
 
 
 delays :: (MonadIO m, Applicative f) => Double -> Stream f m r
 delays seconds = loop where
   loop = Effect $ liftIO (threadDelay delay) >> return (Step (pure loop))
   delay = fromInteger (truncate (1000000 * seconds))
-{-#INLINABLE delays #-}
+{-# INLINABLE delays #-}
 
 -- {-| Permit streamed actions to proceed unless the clock has run out.
 --
@@ -1275,7 +1296,7 @@
 --     loop str
 --   where
 --   cutoff = fromInteger (truncate (1000000000 * seconds))
--- {-#INLINABLE period #-}
+-- {-# INLINABLE period #-}
 --
 --
 -- {-| Divide a succession of phases according to a specified time interval. If time runs out
@@ -1339,11 +1360,11 @@
 untilJust act = loop where
   loop = Effect $ do
     m <- act
-    case m of
-      Nothing -> return $ Step $ pure loop
-      Just a -> return $ Return a
-    
-    
+    return $ case m of
+      Nothing -> Step $ pure loop
+      Just a  -> Return a
+
+
 cutoff :: (Monad m, Functor f) => Int -> Stream f m r -> Stream f m (Maybe r)
 cutoff = loop where
   loop 0 _ = return Nothing
@@ -1351,4 +1372,4 @@
       e <- lift $ inspect str
       case e of
         Left r -> return (Just r)
-        Right (frest) -> Step $ fmap (loop (n-1)) frest
+        Right frest -> Step $ fmap (loop (n-1)) frest
diff --git a/src/Streaming/Prelude.hs b/src/Streaming/Prelude.hs
--- a/src/Streaming/Prelude.hs
+++ b/src/Streaming/Prelude.hs
@@ -1,4 +1,4 @@
-{-| This names exported by this module are closely modeled on those in @Prelude@ and @Data.List@,
+{-| The names exported by this module are closely modeled on those in @Prelude@ and @Data.List@,
     but also on
     <http://hackage.haskell.org/package/pipes-4.1.9/docs/Pipes-Prelude.html Pipes.Prelude>,
     <http://hackage.haskell.org/package/pipes-group-1.0.3/docs/Pipes-Group.html Pipes.Group>
@@ -8,7 +8,7 @@
     articulated in the latter two modules. Because we dispense with piping and
     conduiting, the distinction between all of these modules collapses. Some things are
     lost but much is gained: on the one hand, everything comes much closer to ordinary
-    beginning Haskell programming and, on the other, acquires the plasticity of programming 
+    beginning Haskell programming and, on the other, acquires the plasticity of programming
     directly with a general free monad type. The leading type, @Stream (Of a) m r@ is chosen to permit an api
     that is as close as possible to that of @Data.List@ and the @Prelude@.
 
@@ -47,17 +47,11 @@
 > --------------------------------------------------------------------------------------------------------------------
 >
 -}
-{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE DeriveFoldable #-}
-{-# LANGUAGE DeriveFunctor #-}
-{-# LANGUAGE DeriveTraversable #-}
-{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE BangPatterns        #-}
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE RankNTypes          #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeFamilies #-}
-
-{-# OPTIONS_GHC -Wall #-}
+{-# LANGUAGE TypeFamilies        #-}
 
 module Streaming.Prelude (
     -- * Types
@@ -70,21 +64,22 @@
     , stdinLn
     , readLn
     , fromHandle
-    , readFile 
+    , readFile
     , iterate
     , iterateM
     , repeat
     , repeatM
     , replicate
+    , untilLeft
     , untilRight
     , cycle
     , replicateM
     , enumFrom
     , enumFromThen
     , unfoldr
-    
 
 
+
     -- * Consuming streams of elements
     -- $consumers
     , stdoutLn
@@ -92,7 +87,7 @@
     , mapM_
     , print
     , toHandle
-    , writeFile 
+    , writeFile
     , effects
     , erase
     , drained
@@ -138,8 +133,8 @@
     , read
     , show
     , cons
-    , slidingWindow    
-
+    , slidingWindow
+    , wrapEffect
 
     -- * Splitting and inspecting streams of elements
     , next
@@ -235,7 +230,7 @@
     , merge
     , mergeOn
     , mergeBy
-    
+
     -- * Maybes
     -- $maybes
     , catMaybes
@@ -256,19 +251,31 @@
     -- * Basic Type
     , Stream
   ) where
+
 import Streaming.Internal
 
+import Control.Applicative (Applicative (..))
+import Control.Concurrent (threadDelay)
+import Control.Exception (throwIO, try)
 import Control.Monad hiding (filterM, mapM, mapM_, foldM, foldM_, replicateM, sequence)
-import Data.Functor.Identity
-import Data.Functor.Sum
 import Control.Monad.Trans
-import Control.Applicative (Applicative (..))
 import Data.Functor (Functor (..), (<$))
-
-import qualified Prelude as Prelude
+import Data.Functor.Compose
+import Data.Functor.Identity
+import Data.Functor.Of
+import Data.Functor.Sum
+import Data.Monoid (Monoid (mappend, mempty))
+import Data.Ord (Ordering (..), comparing)
+import Foreign.C.Error (Errno(Errno), ePIPE)
+import Text.Read (readMaybe)
 import qualified Data.Foldable as Foldable
+import qualified Data.IntSet as IntSet
 import qualified Data.Sequence as Seq
-import Text.Read (readMaybe)
+import qualified Data.Set as Set
+import qualified GHC.IO.Exception as G
+import qualified Prelude
+import qualified System.IO as IO
+
 import Prelude hiding (map, mapM, mapM_, filter, drop, dropWhile, take, mconcat
                       , sum, product, iterate, repeat, cycle, replicate, splitAt
                       , takeWhile, enumFrom, enumFromTo, enumFromThen, length
@@ -277,24 +284,26 @@
                       , minimum, maximum, elem, notElem, all, any, head
                       , last, foldMap)
 
-import qualified GHC.IO.Exception as G
-import qualified System.IO as IO
-import Foreign.C.Error (Errno(Errno), ePIPE)
-import Control.Exception (throwIO, try)
-import Data.Monoid (Monoid (mappend, mempty))
-import Control.Concurrent (threadDelay)
-import Data.Functor.Compose
-import Data.Functor.Of
-import qualified Data.Set as Set
-import qualified Data.IntSet as IntSet
-import Data.Ord (Ordering (..), comparing)
 
+
+-- $setup
+-- >>> import Control.Applicative
+-- >>> import qualified Control.Foldl as L
+-- >>> import Data.Bifunctor (first)
+-- >>> import Data.Function ((&))
+-- >>> import Data.IORef
+-- >>> import Data.Vector (Vector)
+-- >>> import qualified Streaming.Prelude as S
+-- >>> import qualified System.IO
+-- >>> import Text.Read (readEither)
+
+
 -- instance (Eq a) => Eq1 (Of a) where eq1 = (==)
 -- instance (Ord a) => Ord1 (Of a) where compare1 = compare
 -- instance (Read a) => Read1 (Of a) where readsPrec1 = readsPrec
 -- instance (Show a) => Show1 (Of a) where showsPrec1 = showsPrec
 
-{-| Note that 'lazily', 'strictly', 'fst'', and 'mapOf' are all so-called /natural transformations/ on the primitive @Of a@ functor
+{-| Note that 'lazily', 'strictly', 'fst'', and 'mapOf' are all so-called /natural transformations/ on the primitive @Of a@ functor.
     If we write
 
 >  type f ~~> g = forall x . f x -> g x
@@ -319,7 +328,7 @@
   This rests on recognizing that @mapOf@ is a natural transformation; note though
   that it results in such a transformation as well:
 
->  S.map :: (a -> b) -> Stream (Of a) m ~> Stream (Of b) m
+>  S.map :: (a -> b) -> Stream (Of a) m ~~> Stream (Of b) m
 
   Thus we can @maps@ it in turn.
 
@@ -355,10 +364,10 @@
 
 fst' :: Of a b -> a
 fst' (a :> _) = a
-{-#INLINE fst' #-}
+{-# INLINE fst' #-}
 snd' :: Of a b -> b
 snd' (_ :> b) = b
-{-#INLINE snd' #-}
+{-# INLINE snd' #-}
 
 {-| Map a function over the first element of an @Of@ pair
 
@@ -379,18 +388,18 @@
  -}
 
 mapOf :: (a -> b) -> Of a r -> Of b r
-mapOf f (a:> b) = (f a :> b)
-{-#INLINE mapOf #-}
+mapOf f (a :> b) = f a :> b
+{-# INLINE mapOf #-}
 
 {-| A lens into the first element of a left-strict pair -}
 _first :: Functor f => (a -> f a') -> Of a b -> f (Of a' b)
-_first afb (a:>b) = fmap (\c -> (c:>b)) (afb a)
+_first afb (a :> b) = fmap (\c -> c :> b) (afb a)
 {-# INLINE _first #-}
 
 {-| A lens into the second element of a left-strict pair -}
 _second :: Functor f => (b -> f b') -> Of a b -> f (Of a b')
-_second afb (a:>b) = fmap (\c -> (a:>c)) (afb b)
-{-#INLINABLE _second #-}
+_second afb (a :> b) = fmap (\c -> a :> c) (afb b)
+{-# INLINABLE _second #-}
 
 all :: Monad m => (a -> Bool) -> Stream (Of a) m r -> m (Of Bool r)
 all thus = loop True where
@@ -402,7 +411,7 @@
       else do
         r <- effects rest
         return (False :> r)
-{-#INLINABLE all #-}
+{-# INLINABLE all #-}
 
 all_ :: Monad m => (a -> Bool) -> Stream (Of a) m r -> m Bool
 all_ thus = loop True where
@@ -412,7 +421,7 @@
     Step (a :> rest) -> if thus a
       then loop True rest
       else return False
-{-#INLINABLE all_ #-}
+{-# INLINABLE all_ #-}
 
 
 any :: Monad m => (a -> Bool) -> Stream (Of a) m r -> m (Of Bool r)
@@ -425,7 +434,7 @@
         r <- effects rest
         return (True :> r)
       else loop False rest
-{-#INLINABLE any #-}
+{-# INLINABLE any #-}
 
 any_ :: Monad m => (a -> Bool) -> Stream (Of a) m r -> m Bool
 any_ thus = loop False where
@@ -435,7 +444,7 @@
     Step (a :> rest) -> if thus a
       then return True
       else loop False rest
-{-#INLINABLE any_ #-}
+{-# INLINABLE any_ #-}
 
 {-| Break a sequence upon meeting element falls under a predicate,
     keeping it and the rest of the stream as the return value.
@@ -454,8 +463,8 @@
 break thePred = loop where
   loop str = case str of
     Return r         -> Return (Return r)
-    Effect m          -> Effect $ fmap loop m
-    Step (a :> rest) -> if (thePred a)
+    Effect m         -> Effect $ fmap loop m
+    Step (a :> rest) -> if thePred a
       then Return (Step (a :> rest))
       else Step (a :> loop rest)
 {-# INLINABLE break #-}
@@ -465,7 +474,7 @@
    and the element that breaks it will be put after the break.
    This function is easiest to use with 'Control.Foldl.purely'
 
->>>  rest <- each [1..10] & L.purely S.breakWhen L.sum (>10) & S.print
+>>> rest <- each [1..10] & L.purely S.breakWhen L.sum (>10) & S.print
 1
 2
 3
@@ -486,7 +495,7 @@
         Return r -> return (return r)
         Effect mn  -> Effect $ fmap (loop0 x) mn
         Step (a :> rest) -> loop a (step x a) rest
-    loop a !x stream = do
+    loop a !x stream =
       if thePred (done x)
         then return (yield a >> stream)
         else case stream of
@@ -497,17 +506,17 @@
             loop a' (step x a') rest
 {-# INLINABLE breakWhen #-}
 
--- -- Break during periods where the predicate is not satisfied, grouping the periods when it is.
---
--- >>> S.print $ mapped S.toList $ S.breaks not $ S.each [False,True,True,False,True,True,False]
--- [True,True]
--- [True,True]
--- >>> S.print $ mapped S.toList $ S.breaks id $ S.each [False,True,True,False,True,True,False]
--- [False]
--- [False]
--- [False]
---
--- -}
+{-| Break during periods where the predicate is not satisfied, grouping the periods when it is.
+
+>>> S.print $ mapped S.toList $ S.breaks not $ S.each [False,True,True,False,True,True,False]
+[True,True]
+[True,True]
+>>> S.print $ mapped S.toList $ S.breaks id $ S.each [False,True,True,False,True,True,False]
+[False]
+[False]
+[False]
+
+-}
 breaks
   :: Monad m =>
      (a -> Bool) -> Stream (Of a) m r -> Stream (Stream (Of a) m) m r
@@ -520,9 +529,10 @@
        if not (thus a)
           then Step $ fmap loop (yield a >> break thus p')
           else loop p'
-{-#INLINABLE breaks #-}
+{-# INLINABLE breaks #-}
 
-{-| Apply an action to all values, re-yielding each
+{-| Apply an action to all values, re-yielding each.
+    The return value (@y@) of the function is ignored.
 
 >>> S.product $ S.chain Prelude.print $ S.each [1..5]
 1
@@ -531,15 +541,17 @@
 4
 5
 120 :> ()
+
+See also 'mapM' for a variant of this which uses the return value of the function to transorm the values in the stream.
 -}
 
-chain :: Monad m => (a -> m ()) -> Stream (Of a) m r -> Stream (Of a) m r
+chain :: Monad m => (a -> m y) -> Stream (Of a) m r -> Stream (Of a) m r
 chain f = loop where
   loop str = case str of
     Return r -> return r
     Effect mn  -> Effect (fmap loop mn)
     Step (a :> rest) -> Effect $ do
-      f a
+      _ <- f a
       return (Step (a :> loop rest))
 {-# INLINABLE chain #-}
 
@@ -554,7 +566,7 @@
 'z'
 
     Note that it also has the effect of 'Data.Maybe.catMaybes', 'Data.Either.rights'
-    'map snd' and such-like operations.
+    @map snd@ and such-like operations.
 
 >>> S.print $ S.concat $ S.each [Just 1, Nothing, Just 2]
 1
@@ -616,7 +628,7 @@
 
 cycle :: (Monad m, Functor f) => Stream f m r -> Stream f m s
 cycle str = loop where loop = str >> loop
-{-#INLINABLE cycle #-}
+{-# INLINABLE cycle #-}
 
 
 {-| Interpolate a delay of n seconds between yields.
@@ -632,7 +644,7 @@
         yield a
         liftIO $ threadDelay pico
         loop rest
-{-#INLINABLE delay #-}
+{-# INLINABLE delay #-}
 
 
 
@@ -661,14 +673,14 @@
 -}
 drained :: (Monad m, Monad (t m), MonadTrans t) => t m (Stream (Of a) m r) -> t m r
 drained tms = tms >>= lift . effects
-{-#INLINE drained #-}
+{-# INLINE drained #-}
 
 -- ---------------
 -- drop
 -- ---------------
 {-|  Ignore the first n elements of a stream, but carry out the actions
 
->>> S.toList $ S.drop 2 $  S.replicateM 5 getLine
+>>> S.toList $ S.drop 2 $ S.replicateM 5 getLine
 a<Enter>
 b<Enter>
 c<Enter>
@@ -681,9 +693,6 @@
 
 >>> S.toList $ concats $ maps (S.drop 4) $ chunksOf 5 $ each [1..20]
 [5,10,15,20] :> ()
-
-
-
   -}
 
 drop :: (Monad m) => Int -> Stream (Of a) m r -> Stream (Of a) m r
@@ -767,8 +776,21 @@
     Return r         -> return r
     Effect m         -> m >>= loop
     Step (_ :> rest) -> loop rest
-{-#INLINABLE effects #-}
+{-# INLINABLE effects #-}
 
+{-| Before evaluating the monadic action returning the next step in the 'Stream', @wrapEffect@
+    extracts the value in a monadic computation @m a@ and passes it to a computation @a -> m y@.
+
+-}
+wrapEffect :: (Monad m, Functor f) => m a -> (a -> m y) -> Stream f m r -> Stream f m r
+wrapEffect m f = loop where
+  loop stream = do
+    x <- lift m
+    step <- lift $ inspect stream
+    _ <- lift $ f x
+    either pure loop' step
+  loop' stream = wrap (fmap loop stream)
+
 {-| Exhaust a stream remembering only whether @a@ was an element.
 
 -}
@@ -783,7 +805,7 @@
       if a == a'
         then fmap (True :>) (effects rest)
         else loop False rest
-{-#INLINABLE elem #-}
+{-# INLINABLE elem #-}
 
 elem_ :: (Monad m, Eq a) => a -> Stream (Of a) m r -> m Bool
 elem_ a' = loop False where
@@ -795,7 +817,7 @@
       if a == a'
         then return True
         else loop False rest
-{-#INLINABLE elem_ #-}
+{-# INLINABLE elem_ #-}
 
 -- -----
 -- enumFrom
@@ -803,8 +825,8 @@
 
 {-| An infinite stream of enumerable values, starting from a given value.
     It is the same as @S.iterate succ@.
-   Because their return type is polymorphic, @enumFrom@ and @enumFromThen@
-   (and @iterate@ are useful for example with @zip@
+   Because their return type is polymorphic, @enumFrom@, @enumFromThen@
+   and @iterate@ are useful for example with @zip@
    and @zipWith@, which require the same return type in the zipped streams.
    With @each [1..]@ the following bit of connect-and-resume would be impossible:
 
@@ -870,7 +892,7 @@
       else loop as
 {-# INLINE filter #-}  -- ~ 10% faster than INLINABLE in simple bench
 
-                         
+
 -- ---------------
 -- filterM
 -- ---------------
@@ -913,10 +935,10 @@
 {- $folds
     Use these to fold the elements of a 'Stream'.
 
->>> S.fold_ (+) 0 id $ S.each [1..0]
-50
+>>> S.fold_ (+) 0 id $ S.each [1..10]
+55
 
-    The general folds 'fold', fold_', 'foldM' and 'foldM_' are arranged
+    The general folds 'fold', 'fold_', 'foldM' and 'foldM_' are arranged
     for use with @Control.Foldl@ 'Control.Foldl.purely' and 'Control.Foldl.impurely'
 
 >>> L.purely fold_ L.sum $ each [1..10]
@@ -924,8 +946,8 @@
 >>> L.purely fold_ (liftA3 (,,) L.sum L.product L.list) $ each [1..10]
 (55,3628800,[1,2,3,4,5,6,7,8,9,10])
 
-    All functions marked with an underscore omit
-    (e.g. @fold_@, @sum_@) the stream's return value in a left-strict pair.
+    All functions marked with an underscore
+    (e.g. @fold_@, @sum_@) omit the stream's return value in a left-strict pair.
     They are good for exiting streaming completely,
     but when you are, e.g. @mapped@-ing over a @Stream (Stream (Of a) m) m r@,
     which is to be compared with @[[a]]@. Specializing, we have e.g.
@@ -962,7 +984,7 @@
 -}
 fold_ :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Stream (Of a) m r -> m b
 fold_ step begin done = fmap (\(a :> _) -> a) . fold step begin done
-{-#INLINE fold_ #-}
+{-# INLINE fold_ #-}
 
 {-| Strict fold of a 'Stream' of elements that preserves the return value.
     The third parameter will often be 'id' where a fold is written by hand:
@@ -1006,7 +1028,7 @@
 {-# INLINE fold #-}
 
 
-{-| Strict, monadic fold of the elements of a 'Stream (Of a)'
+{-| Strict, monadic fold of the elements of a @Stream (Of a)@
 
 > Control.Foldl.impurely foldM :: Monad m => FoldM a b -> Stream (Of a) m () -> m b
 -}
@@ -1014,16 +1036,16 @@
     :: Monad m
     => (x -> a -> m x) -> m x -> (x -> m b) -> Stream (Of a) m r -> m b
 foldM_ step begin done = fmap (\(a :> _) -> a) . foldM step begin done
-{-#INLINE foldM_ #-}
+{-# INLINE foldM_ #-}
 
-{-| Strict, monadic fold of the elements of a 'Stream (Of a)'
+{-| Strict, monadic fold of the elements of a @Stream (Of a)@
 
 > Control.Foldl.impurely foldM' :: Monad m => FoldM a b -> Stream (Of a) m r -> m (b, r)
 
    Thus to accumulate the elements of a stream as a vector, together with a random
    element we might write:
 
->>>  L.impurely S.foldM (liftA2 (,) L.vector L.random) $ each [1..10::Int] :: IO (Of (U.Vector Int,Maybe Int) ())
+>>> L.impurely S.foldM (liftA2 (,) L.vectorM L.random) $ each [1..10::Int] :: IO (Of (Vector Int, Maybe Int) ())
 ([1,2,3,4,5,6,7,8,9,10],Just 9) :> ()
 
 -}
@@ -1055,7 +1077,7 @@
 --       b <- done x'
 --       return (b :> r)
 --   where seq = Prelude.seq
--- {-#INLINE foldM #-}
+-- {-# INLINE foldM #-}
 
 {-| A natural right fold for consuming a stream of elements.
     See also the more general 'iterTM' in the 'Streaming' module
@@ -1096,11 +1118,11 @@
 -- | @for@ replaces each element of a stream with an associated stream. Note that the
 -- associated stream may layer any functor.
 for :: (Monad m, Functor f) => Stream (Of a) m r -> (a -> Stream f m x) -> Stream f m r
-for str0 act = loop str0 where
+for str0 f = loop str0 where
   loop str = case str of
     Return r         -> Return r
-    Effect m          -> Effect $ fmap loop m
-    Step (a :> rest) -> act a *> loop rest
+    Effect m         -> Effect $ fmap loop m
+    Step (a :> as) -> f a *> loop as
 {-# INLINABLE for #-}
 
 -- -| Group layers of any functor by comparisons on a preliminary annotation
@@ -1166,7 +1188,7 @@
 -}
 group :: (Monad m, Eq a) => Stream (Of a) m r -> Stream (Stream (Of a) m) m r
 group = groupBy (==)
-{-#INLINE group #-}
+{-# INLINE group #-}
 
 
 head :: Monad m => Stream (Of a) m r -> m (Of (Maybe a) r)
@@ -1174,15 +1196,26 @@
   Return r            -> return (Nothing :> r)
   Effect m            -> m >>= head
   Step (a :> rest)    -> effects rest >>= \r -> return (Just a :> r)
-{-#INLINABLE head #-}
+{-# INLINABLE head #-}
 
 head_ :: Monad m => Stream (Of a) m r -> m (Maybe a)
 head_ str = case str of
   Return _ -> return Nothing
   Effect m -> m >>= head_
   Step (a :> _) -> return (Just a)
-{-#INLINABLE head_ #-}
+{-# INLINABLE head_ #-}
 
+
+{-| Intersperse given value between each element of the stream.
+
+>>> S.print $ S.intersperse 0 $ each [1,2,3]
+1
+0
+2
+0
+3
+
+-}
 intersperse :: Monad m => a -> Stream (Of a) m r -> Stream (Of a) m r
 intersperse x str = case str of
     Return r -> Return r
@@ -1193,7 +1226,7 @@
     Return r -> Step (a :> Return r)
     Effect m -> Effect (fmap (loop a) m)
     Step (b :> rest) -> Step (a :> Step (x :> loop b rest))
-{-#INLINABLE intersperse #-}
+{-# INLINABLE intersperse #-}
 
 
 
@@ -1230,7 +1263,7 @@
       Just_ a  -> return (Just a :> r)
     Effect m            -> m >>= loop mb
     Step (a :> rest)  -> loop (Just_ a) rest
-{-#INLINABLE last #-}
+{-# INLINABLE last #-}
 
 
 
@@ -1242,7 +1275,7 @@
       Just_ a  -> return (Just a)
     Effect m -> m >>= loop mb
     Step (a :> rest) -> loop (Just_ a) rest
-{-#INLINABLE last_ #-}
+{-# INLINABLE last_ #-}
 
 
 -- ---------------
@@ -1251,13 +1284,13 @@
 
 {-| Run a stream, remembering only its length:
 
->>> S.length $ S.each [1..10]
+>>> runIdentity $ S.length_ (S.each [1..10] :: Stream (Of Int) Identity ())
 10
 
 -}
 length_ :: Monad m => Stream (Of a) m r -> m Int
 length_ = fold_ (\n _ -> n + 1) 0 id
-{-#INLINE length_#-}
+{-# INLINE length_ #-}
 
 {-| Run a stream, keeping its length and its return value.
 
@@ -1271,7 +1304,7 @@
 
 length :: Monad m => Stream (Of a) m r -> m (Of Int r)
 length = fold (\n _ -> n + 1) 0 id
-{-#INLINE length #-}
+{-# INLINE length #-}
 -- ---------------
 -- map
 -- ---------------
@@ -1284,7 +1317,7 @@
 -}
 
 map :: Monad m => (a -> b) -> Stream (Of a) m r -> Stream (Of b) m r
-map f =  maps (\(x :> rest) -> f x :> rest)
+map f = maps (\(x :> rest) -> f x :> rest)
 -- loop where  --
   -- loop stream = case stream of
   --   Return r -> Return r
@@ -1306,12 +1339,14 @@
 400
 500
 600
+
+See also 'chain' for a variant of this which ignores the return value of the function and just uses the side effects.
 -}
 mapM :: Monad m => (a -> m b) -> Stream (Of a) m r -> Stream (Of b) m r
 mapM f = loop where
   loop str = case str of
     Return r       -> Return r
-    Effect m        -> Effect (fmap loop m)
+    Effect m       -> Effect (fmap loop m)
     Step (a :> as) -> Effect $ do
       a' <- f a
       return (Step (a' :> loop as) )
@@ -1335,7 +1370,7 @@
 49 :> ()
 
 -}
-mapM_ :: Monad m => (a -> m b) -> Stream (Of a) m r -> m r
+mapM_ :: Monad m => (a -> m x) -> Stream (Of a) m r -> m r
 mapM_ f = loop where
   loop str = case str of
     Return r -> return r
@@ -1350,8 +1385,7 @@
 
 > let noteBeginning text x = putStrLn text >> return text
 
-     this puts the
-     is completely functor-general
+     this is completely functor-general
 
      @maps@ and @mapped@ obey these rules:
 
@@ -1372,7 +1406,7 @@
 
 mapped :: (Monad m, Functor f) => (forall x . f x -> m (g x)) -> Stream f m r -> Stream g m r
 mapped = mapsM
-{-#INLINE mapped #-}
+{-# INLINE mapped #-}
 
 {-| A version of 'mapped' that imposes a 'Functor' constraint on the target functor rather
     than the source functor. This version should be preferred if 'fmap' on the target
@@ -1402,7 +1436,7 @@
 
 {-| Fold streamed items into their monoidal sum
 
->>> S.mconcat $ S.take 2 $ S.map (Data.Monoid.Last . Just) (S.stdinLn)
+>>> S.mconcat $ S.take 2 $ S.map (Data.Monoid.Last . Just) S.stdinLn
 first<Enter>
 last<Enter>
 Last {getLast = Just "last"} :> ()
@@ -1426,19 +1460,19 @@
 minimum_ = fold_ (\m a -> case m of Nothing_ -> Just_ a ; Just_ a' -> Just_ (min a a'))
                  Nothing_
                  (\m -> case m of Nothing_ -> Nothing; Just_ r -> Just r)
-{-#INLINE minimum_ #-}
+{-# INLINE minimum_ #-}
 
 maximum :: (Monad m, Ord a) => Stream (Of a) m r -> m (Of (Maybe a) r)
 maximum = fold (\m a -> case m of Nothing_ -> Just_ a ; Just_ a' -> Just_ (max a a'))
                Nothing_
                (\m -> case m of Nothing_ -> Nothing; Just_ r -> Just r)
-{-#INLINE maximum #-}
+{-# INLINE maximum #-}
 
 maximum_ :: (Monad m, Ord a) => Stream (Of a) m r -> m (Maybe a)
 maximum_ = fold_ (\m a -> case m of Nothing_ -> Just_ a ; Just_ a' -> Just_ (max a a'))
                  Nothing_
                  (\m -> case m of Nothing_ -> Nothing; Just_ r -> Just r)
-{-#INLINE maximum_ #-}
+{-# INLINE maximum_ #-}
 
 {-| The standard way of inspecting the first item in a stream of elements, if the
      stream is still \'running\'. The @Right@ case contains a
@@ -1446,7 +1480,7 @@
      There is no reason to prefer @inspect@ since, if the @Right@ case is exposed,
      the first element in the pair will have been evaluated to whnf.
 
-> next :: Monad m => Stream (Of a) m r -> m (Either r (a, Stream (Of a) m r))
+> next    :: Monad m => Stream (Of a) m r -> m (Either r    (a, Stream (Of a) m r))
 > inspect :: Monad m => Stream (Of a) m r -> m (Either r (Of a (Stream (Of a) m r)))
 
      Interoperate with @pipes@ producers thus:
@@ -1457,7 +1491,7 @@
      Similarly:
 
 > IOStreams.unfoldM (fmap (either (const Nothing) Just) . next) :: Stream (Of a) IO b -> IO (InputStream a)
-> Conduit.unfoldM (fmap (either (const Nothing) Just) . next)   :: Stream (Of a) m r -> Source a m r
+> Conduit.unfoldM   (fmap (either (const Nothing) Just) . next) :: Stream (Of a) m r -> Source a m r
 
      But see 'uncons', which is better fitted to these @unfoldM@s
 -}
@@ -1484,7 +1518,7 @@
       if a == a'
         then fmap (False :>) (effects rest)
         else loop True rest
-{-#INLINABLE notElem #-}
+{-# INLINABLE notElem #-}
 
 notElem_ :: (Monad m, Eq a) => a -> Stream (Of a) m r -> m Bool
 notElem_ a' = loop True where
@@ -1496,13 +1530,13 @@
       if a == a'
         then return False
         else loop True rest
-{-#INLINABLE notElem_ #-}
+{-# INLINABLE notElem_ #-}
 
 
 {-| Remove repeated elements from a Stream. 'nubOrd' of course accumulates a 'Data.Set.Set' of
     elements that have already been seen and should thus be used with care.
 
->>> S.toList_ $ S.nubOrd $ S.take 5 S.readLn :: IO ([Int])
+>>> S.toList_ $ S.nubOrd $ S.take 5 S.readLn :: IO [Int]
 1<Enter>
 2<Enter>
 3<Enter>
@@ -1598,7 +1632,7 @@
 
 {-| Fold a 'Stream' of numbers into their product with the return value
 
->  maps' product' :: Stream (Stream (Of Int)) m r -> Stream (Of Int) m r
+>  mapped product :: Stream (Stream (Of Int)) m r -> Stream (Of Int) m r
 -}
 product :: (Monad m, Num a) => Stream (Of a) m r -> m (Of a r)
 product = fold (*) 1 id
@@ -1643,7 +1677,7 @@
 
 {-| Repeat a monadic action /ad inf./, streaming its results.
 
->>>  S.toList $ S.take 2 $ repeatM getLine
+>>> S.toList $ S.take 2 $ repeatM getLine
 one<Enter>
 two<Enter>
 ["one","two"]
@@ -1701,7 +1735,7 @@
       Just a  -> return (Step (a :> loop))
 {-# INLINABLE reread #-}
 
-{-| Strict left scan, streaming, e.g. successive partial results. The seed 
+{-| Strict left scan, streaming, e.g. successive partial results. The seed
     is yielded first, before any action of finding the next element is performed.
 
 
@@ -1723,34 +1757,34 @@
 -}
 scan :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Stream (Of a) m r -> Stream (Of b) m r
 scan step begin done str = Step (done begin :> loop begin str)
-  where                   
-  loop !acc stream = do
+  where
+  loop !acc stream =
     case stream of
       Return r -> Return r
       Effect m -> Effect (fmap (loop acc) m)
-      Step (a :> rest) -> 
-        let !acc' = step acc a 
+      Step (a :> rest) ->
+        let !acc' = step acc a
         in Step (done acc' :> loop acc' rest)
-{-#INLINABLE scan #-}
+{-# INLINABLE scan #-}
 
 {-| Strict left scan, accepting a monadic function. It can be used with
     'FoldM's from @Control.Foldl@ using 'impurely'. Here we yield
     a succession of vectors each recording
 
->>> let v =  L.impurely scanM L.vector $ each [1..4::Int] :: Stream (Of (U.Vector Int)) IO ()
+>>> let v = L.impurely scanM L.vectorM $ each [1..4::Int] :: Stream (Of (Vector Int)) IO ()
 >>> S.print v
-fromList []
-fromList [1]
-fromList [1,2]
-fromList [1,2,3]
-fromList [1,2,3,4]
+[]
+[1]
+[1,2]
+[1,2,3]
+[1,2,3,4]
 
 -}
 scanM :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> Stream (Of a) m r -> Stream (Of b) m r
 scanM step begin done str = Effect $ do
     x <- begin
     b <- done x
-    return (Step (b :> loop x str))  
+    return (Step (b :> loop x str))
   where
     loop !x stream = case stream of -- note we have already yielded from x
       Return r -> Return r
@@ -1765,8 +1799,7 @@
         )
 {-# INLINABLE scanM #-}
 
-{- Label each element in a stream with a value accumulated according to a fold.
-
+{-| Label each element in a stream with a value accumulated according to a fold.
 
 >>> S.print $ S.scanned (*) 1 id $ S.each [100,200,300]
 (100,100)
@@ -1780,16 +1813,14 @@
 
 -}
 
-data Maybe' a = Just' a | Nothing'
-
 scanned :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Stream (Of a) m r -> Stream (Of (a,b)) m r
 scanned step begin done = loop Nothing' begin
   where
-    loop !m !x stream = do
+    loop !m !x stream =
       case stream of
         Return r -> return r
         Effect mn  -> Effect $ fmap (loop m x) mn
-        Step (a :> rest) -> do
+        Step (a :> rest) ->
           case m of
             Nothing' -> do
               let !acc = step x a
@@ -1801,30 +1832,7 @@
               loop (Just' a) (step x a) rest
 {-# INLINABLE scanned #-}
 
-
-{-| Streams the number of seconds from the beginning of action
-
-    Thus, to mark times of user input we might write something like:
-
->>> S.toList $ S.take 3 $ S.zip S.seconds S.stdinLn
-a<Enter>
-b<Enter>
-c<Enter>
-[(0.0,"a"),(1.088711,"b"),(3.7289649999999996,"c")] :> ()
-
-   To restrict user input to some number of seconds, we might write:
-
->>> S.toList $ S.map fst $ S.zip S.stdinLn $ S.takeWhile (< 3) S.seconds
-one<Enter>
-two<Enter>
-three<Enter>
-four<Enter>
-five<Enter>
-["one","two","three","four","five"] :> ()
-
-   This of course does not interrupt an action that has already begun.
-
-  -}
+data Maybe' a = Just' a | Nothing'
 
 -- ---------------
 -- sequence
@@ -1875,15 +1883,16 @@
 55 :> ()
 
 >>> (n :> rest)  <- S.sum $ S.splitAt 3 $ each [1..10]
->>> print n
+>>> System.IO.print n
 6
 >>> (m :> rest') <- S.sum $ S.splitAt 3 rest
->>> print m
+>>> System.IO.print m
 15
 >>> S.print rest'
 7
 8
 9
+10
 
 -}
 sum :: (Monad m, Num a) => Stream (Of a) m r -> m (Of a r)
@@ -1926,7 +1935,7 @@
          if a /= t
             then Step (fmap loop (yield a >> break (== t) rest))
             else loop rest
-{-#INLINABLE split #-}
+{-# INLINABLE split #-}
 
 {-| Split a succession of layers after some number, returning a streaming or
     effectful pair. This function is the same as the 'splitsAt' exported by the
@@ -1958,7 +1967,7 @@
     Return r         -> Return r
     Effect m         -> Effect (fmap loop m)
     Step (a :> rest) -> Step (loop rest <$ f a)
-{-#INLINABLE subst #-}
+{-# INLINABLE subst #-}
 -- ---------------
 -- take
 -- ---------------
@@ -1972,7 +1981,7 @@
 >>> S.toList $ S.take 3 $ each "with"
 "wit" :> ()
 
->>> runResourceT $ S.stdoutLn $ S.take 3 $ S.readFile "stream.hs"
+>>> S.readFile "stream.hs" (S.stdoutLn . S.take 3)
 import Streaming
 import qualified Streaming.Prelude as S
 import Streaming.Prelude (each, next, yield)
@@ -2030,7 +2039,7 @@
 {-# INLINE takeWhileM #-}
 
 
-{-| Convert an effectful 'Stream (Of a)' into a list of @as@
+{-| Convert an effectful @Stream (Of a)@ into a list of @as@
 
     Note: Needless to say, this function does not stream properly.
     It is basically the same as Prelude 'mapM' which, like 'replicateM',
@@ -2045,22 +2054,23 @@
 
 {-| Convert an effectful 'Stream' into a list alongside the return value
 
->  mapped toList :: Stream (Stream (Of a)) m r -> Stream (Of [a]) m
+>  mapped toList :: Stream (Stream (Of a) m) m r -> Stream (Of [a]) m r
 
-    Like 'toList_', 'toList' breaks streaming; unlike 'toList_' it /preserves the return value/ 
+    Like 'toList_', 'toList' breaks streaming; unlike 'toList_' it /preserves the return value/
     and thus is frequently useful with e.g. 'mapped'
 
 >>> S.print $ mapped S.toList $ chunksOf 3 $ each [1..9]
 [1,2,3]
 [4,5,6]
 [7,8,9]
+
 >>> S.print $ mapped S.toList $ chunksOf 2 $ S.replicateM 4 getLine
 s<Enter>
 t<Enter>
 ["s","t"]
 u<Enter>
 v<Enter>
-["u","v"] 
+["u","v"]
 -}
 toList :: Monad m => Stream (Of a) m r -> m (Of [a] r)
 toList = fold (\diff a ls -> diff (a: ls)) id (\diff -> diff [])
@@ -2121,6 +2131,18 @@
 {-# INLINABLE unfoldr #-}
 
 -- ---------------------------------------
+-- untilLeft
+-- ---------------------------------------
+untilLeft :: Monad m => m (Either r a) -> Stream (Of a) m r
+untilLeft act = Effect loop where
+  loop = do
+    e <- act
+    case e of
+      Right a -> return (Step (a :> Effect loop))
+      Left r -> return (Return r)
+{-# INLINABLE untilLeft #-}
+
+-- ---------------------------------------
 -- untilRight
 -- ---------------------------------------
 untilRight :: Monad m => m (Either a r) -> Stream (Of a) m r
@@ -2130,7 +2152,7 @@
     case e of
       Right r -> return (Return r)
       Left a -> return (Step (a :> Effect loop))
-{-#INLINABLE untilRight #-}
+{-# INLINABLE untilRight #-}
 
 -- ---------------------------------------
 -- with
@@ -2144,7 +2166,7 @@
 > with = flip subst
 > subst = flip with
 
->>> with (each [1..3]) (yield . show) & intercalates (yield "--") & S.stdoutLn
+>>> with (each [1..3]) (yield . Prelude.show) & intercalates (yield "--") & S.stdoutLn
 1
 --
 2
@@ -2157,7 +2179,7 @@
     Return r         -> Return r
     Effect m         -> Effect (fmap loop m)
     Step (a :> rest) -> Step (loop rest <$ f a)
-{-#INLINABLE with #-}
+{-# INLINABLE with #-}
 
 -- ---------------------------------------
 -- yield
@@ -2169,7 +2191,7 @@
 hello
 
 >>> S.sum $ do {yield 1; yield 2; yield 3}
-6
+6 :> ()
 
 >>> let number = lift (putStrLn "Enter a number:") >> lift readLn >>= yield :: Stream (Of Int) IO ()
 >>> S.toList $ do {number; number; number}
@@ -2189,18 +2211,18 @@
 
 -- | Zip two 'Stream's
 zip :: Monad m
-    => (Stream (Of a) m r)
-    -> (Stream (Of b) m r)
-    -> (Stream (Of (a,b)) m r)
+    => Stream (Of a) m r
+    -> Stream (Of b) m r
+    -> Stream (Of (a,b)) m r
 zip = zipWith (,)
 {-# INLINE zip #-}
 
 -- | Zip two 'Stream's using the provided combining function
 zipWith :: Monad m
     => (a -> b -> c)
-    -> (Stream (Of a) m r)
-    -> (Stream (Of b) m r)
-    -> (Stream (Of c) m r)
+    -> Stream (Of a) m r
+    -> Stream (Of b) m r
+    -> Stream (Of c) m r
 zipWith f = loop
   where
     loop str0 str1 = case str0 of
@@ -2241,10 +2263,10 @@
 
 -- | Zip three 'Stream's together
 zip3 :: Monad m
-    => (Stream (Of a) m r)
-    -> (Stream (Of b) m r)
-    -> (Stream (Of c) m r)
-    -> (Stream (Of (a,b,c)) m r)
+     => Stream (Of a) m r
+     -> Stream (Of b) m r
+     -> Stream (Of c) m r
+     -> Stream (Of (a,b,c)) m r
 zip3 = zipWith3 (,,)
 {-# INLINABLE zip3 #-}
 
@@ -2292,7 +2314,7 @@
 -}
 
 readLn :: (MonadIO m, Read a) => Stream (Of a) m ()
-readLn = loop where 
+readLn = loop where
   loop = do
     eof <- liftIO IO.isEOF
     unless eof $ do
@@ -2307,7 +2329,7 @@
 
     Terminates on end of input
 
->>> IO.withFile "/usr/share/dict/words" IO.ReadMode $ S.stdoutLn . S.take 3 . S.drop 50000 .  S.fromHandle
+>>> IO.withFile "/usr/share/dict/words" IO.ReadMode $ S.stdoutLn . S.take 3 . S.drop 50000 . S.fromHandle
 deflagrator
 deflate
 deflation
@@ -2348,7 +2370,6 @@
 "hello"
 world<Enter>
 "world"
->>>
 
 -}
 print :: (MonadIO m, Show a) => Stream (Of a) m r -> m r
@@ -2406,7 +2427,7 @@
 hello<Enter>
 world<Enter>
 
->>> S.stdoutLn $ S.readFile "lines.txt"
+>>> S.readFile "lines.txt" S.stdoutLn
 hello
 world
 
@@ -2431,106 +2452,33 @@
 stdoutLn' :: MonadIO m => Stream (Of String) m r -> m r
 stdoutLn' = toHandle IO.stdout
 
-
--- -- * Producers
--- -- $producers
---   stdinLn  --
--- , readLn --
--- , fromHandle --
--- , repeatM --
--- , replicateM --
---
--- -- * Consumers
--- -- $consumers
--- , stdoutLn --
--- , stdoutLn' --
--- , mapM_ --
--- , print --
--- , toHandle --
--- , effects --
---
--- -- * Pipes
--- -- $pipes
--- , map --
--- , mapM --
--- , sequence --
--- , mapFoldable --
--- , filter --
--- , filterM --
--- , take --
--- , takeWhile --
--- , takeWhile' --
--- , drop --
--- , dropWhile --
--- , concat --
--- , elemIndices
--- , findIndices
--- , scan --
--- , scanM --
--- , chain --
--- , read --
--- , show --
--- , seq --
---
--- -- * Folds
--- -- $folds
--- , fold --
--- , fold' --
--- , foldM --
--- , foldM' --
--- , all
--- , any
--- , and
--- , or
--- , elem
--- , notElem
--- , find
--- , findIndex
--- , head
--- , index
--- , last
--- , length
--- , maximum
--- , minimum
--- , null
--- , sum --
--- , product --
--- , toList --
--- , toListM --
--- , toListM' --
---
--- -- * Zips
--- , zip --
--- , zipWith --
---
-
 distinguish :: (a -> Bool) -> Of a r -> Sum (Of a) (Of a) r
 distinguish predicate (a :> b) = if predicate a then InR (a :> b) else InL (a :> b)
-{-#INLINE distinguish #-}
+{-# INLINE distinguish #-}
 
 sumToEither ::Sum (Of a) (Of b) r ->  Of (Either a b) r
 sumToEither s = case s of
   InL (a :> r) -> Left a :> r
   InR (b :> r) -> Right b :> r
-{-#INLINE sumToEither #-}
+{-# INLINE sumToEither #-}
 
 eitherToSum :: Of (Either a b) r -> Sum (Of a) (Of b) r
 eitherToSum s = case s of
   Left a :> r  -> InL (a :> r)
   Right b :> r -> InR (b :> r)
-{-#INLINE eitherToSum #-}
+{-# INLINE eitherToSum #-}
 
 composeToSum ::  Compose (Of Bool) f r -> Sum f f r
 composeToSum x = case x of
   Compose (True :> f) -> InR f
   Compose (False :> f) -> InL f
-{-#INLINE composeToSum #-}
+{-# INLINE composeToSum #-}
 
 sumToCompose :: Sum f f r -> Compose (Of Bool) f r
 sumToCompose x = case x of
   InR f -> Compose (True :> f)
   InL f -> Compose (False :> f)
-{-#INLINE sumToCompose #-}
+{-# INLINE sumToCompose #-}
 
 {-| Store the result of any suitable fold over a stream, keeping the stream for
     further manipulation. @store f = f . copy@ :
@@ -2556,7 +2504,7 @@
    simultaneously, and in constant memory -- as they would be if,
    say, you linked them together with @Control.Fold@:
 
->>> L.impurely S.foldM (liftA3 (\a b c -> (b,c)) (L.sink print) (L.generalize L.sum) (L.generalize L.product)) $ each [1..4]
+>>> L.impurely S.foldM (liftA3 (\a b c -> (b, c)) (L.sink Prelude.print) (L.generalize L.sum) (L.generalize L.product)) $ each [1..4]
 1
 2
 3
@@ -2567,16 +2515,16 @@
    than the corresponding succession of uses of 'store', but by
    constant factor that will be completely dwarfed when any IO is at issue.
 
-   But 'store' / 'copy' is /much/ more powerful, as you can see by reflecting on
+   But 'store' \/ 'copy' is /much/ more powerful, as you can see by reflecting on
    uses like this:
 
->>> S.sum $ S.store (S.sum . mapped S.product . chunksOf 2) $ S.store (S.product . mapped S.sum . chunksOf 2 )$ each [1..6]
+>>> S.sum $ S.store (S.sum . mapped S.product . chunksOf 2) $ S.store (S.product . mapped S.sum . chunksOf 2) $ each [1..6]
 21 :> (44 :> (231 :> ()))
 
    It will be clear that this cannot be reproduced with any combination of lenses,
    @Control.Fold@ folds, or the like.  (See also the discussion of 'copy'.)
 
-   It would conceivable be clearer to import a series of specializations of 'store'.
+   It would conceivably be clearer to import a series of specializations of 'store'.
    It is intended to be used at types like these:
 
 > storeM ::  (forall s m . Monad m => Stream (Of a) m s -> m (Of b s))
@@ -2584,12 +2532,12 @@
 > storeM = store
 >
 > storeMIO :: (forall s m . MonadIO m => Stream (Of a) m s -> m (Of b s))
->          -> ( MonadIO n => Stream (Of a) n r -> Stream (Of a) n (Of b r)
+>          -> (MonadIO n => Stream (Of a) n r -> Stream (Of a) n (Of b r)
 > storeMIO = store
 
     It is clear from these types that we are just using the general instances:
 
-> instance (Functor f, Monad m )  => Monad (Stream f m)
+> instance (Functor f, Monad m)   => Monad (Stream f m)
 > instance (Functor f, MonadIO m) => MonadIO (Stream f m)
 
     We thus can't be touching the elements of the stream, or the final return value.
@@ -2597,7 +2545,7 @@
     like 'MonadResource'.  Thus I can independently filter and write to one file, but
     nub and write to another, or interact with a database and a logfile and the like:
 
->>> runResourceT $ (S.writeFile "hello2.txt" . S.nubOrd) $ store (S.writeFile "hello.txt" . S.filter (/= "world")) $ each ["hello", "world", "goodbye", "world"]
+>>> (S.writeFile "hello2.txt" . S.nubOrd) $ store (S.writeFile "hello.txt" . S.filter (/= "world")) $ each ["hello", "world", "goodbye", "world"]
 >>> :! cat hello.txt
 hello
 goodbye
@@ -2612,7 +2560,7 @@
   :: Monad m =>
      (Stream (Of a) (Stream (Of a) m) r -> t) -> Stream (Of a) m r -> t
 store f x = f (copy x)
-{-#INLINE store #-}
+{-# INLINE store #-}
 
 {-| Duplicate the content of stream, so that it can be acted on twice in different ways,
     but without breaking streaming. Thus, with @each [1,2]@ I might do:
@@ -2627,10 +2575,10 @@
     With copy, I can do these simultaneously:
 
 >>> S.print $ S.stdoutLn $ S.copy $ each ["one","two"]
-one
 "one"
-two
+one
 "two"
+two
 
     'copy' should be understood together with 'effects' and is subject to the rules
 
@@ -2656,7 +2604,7 @@
     using 'Control.Foldl.handles' on an appropriate lens. Some such
     manipulations are simpler and more 'Data.List'-like, using 'copy':
 
->>> L.purely S.fold (liftA2 (,) (L.handles (filtered odd) L.sum) (L.handles (filtered even) L.product)) $ each [1..10]
+>>> L.purely S.fold (liftA2 (,) (L.handles (L.filtered odd) L.sum) (L.handles (L.filtered even) L.product)) $ each [1..10]
 (25,3840) :> ()
 
      becomes
@@ -2703,13 +2651,15 @@
     Return r         -> Return r
     Effect m         -> Effect (fmap loop (lift m))
     Step (a :> rest) -> Effect (Step (a :> Return (Step (a :> loop rest))))
-{-#INLINABLE copy#-}
+{-# INLINABLE copy#-}
 
+{-| An alias for @copy@.
+-}
 duplicate
   :: Monad m =>
      Stream (Of a) m r -> Stream (Of a) (Stream (Of a) m) r
 duplicate = copy
-{-#INLINE duplicate #-}
+{-# INLINE duplicate #-}
 
 {-| The type
 
@@ -2725,7 +2675,7 @@
    This @unzip@ does
    stream, though of course you can spoil this by using e.g. 'toList':
 
->>> let xs =  map (\x-> (x,show x)) [1..5::Int]
+>>> let xs = Prelude.map (\x -> (x, Prelude.show x)) [1..5 :: Int]
 
 >>> S.toList $ S.toList $ S.unzip (S.each xs)
 ["1","2","3","4","5"] :> ([1,2,3,4,5] :> ())
@@ -2770,7 +2720,7 @@
    Return r -> Return r
    Effect m -> Effect (fmap loop (lift m))
    Step ((a,b):> rest) -> Step (a :> Effect (Step (b :> Return (loop rest))))
-{-#INLINABLE unzip #-}
+{-# INLINABLE unzip #-}
 
 
 
@@ -2838,7 +2788,7 @@
           LT -> Step (a :> loop rest0 str1)
           EQ -> Step (a :> loop rest0 str1) -- left-biased
           GT -> Step (b :> loop str0 rest1)
-{-# INLINABLE mergeBy #-}        
+{-# INLINABLE mergeBy #-}
 
 {- $maybes
     These functions discard the 'Nothing's that they encounter. They are analogous
@@ -2847,7 +2797,7 @@
 
 {-| The 'catMaybes' function takes a 'Stream' of 'Maybe's and returns
     a 'Stream' of all of the 'Just' values. 'concat' has the same behavior,
-    but is more general; it works for any foldable container type. 
+    but is more general; it works for any foldable container type.
 -}
 catMaybes :: Monad m => Stream (Of (Maybe a)) m r -> Stream (Of a) m r
 catMaybes = loop where
@@ -2857,12 +2807,12 @@
     Step (ma :> snext) -> case ma of
       Nothing -> loop snext
       Just a -> Step (a :> loop snext)
-{-#INLINABLE catMaybes #-}
+{-# INLINABLE catMaybes #-}
 
 {-| The 'mapMaybe' function is a version of 'map' which can throw out elements. In particular,
     the functional argument returns something of type @'Maybe' b@. If this is 'Nothing', no element
     is added on to the result 'Stream'. If it is @'Just' b@, then @b@ is included in the result 'Stream'.
-    
+
 -}
 mapMaybe :: Monad m => (a -> Maybe b) -> Stream (Of a) m r -> Stream (Of b) m r
 mapMaybe phi = loop where
@@ -2872,42 +2822,42 @@
     Step (a :> snext) -> case phi a of
       Nothing -> loop snext
       Just b -> Step (b :> loop snext)
-{-#INLINABLE mapMaybe #-}
+{-# INLINABLE mapMaybe #-}
 
-{-| 'slidingWindow' accumulates the first @n@ elements of a stream, 
+{-| 'slidingWindow' accumulates the first @n@ elements of a stream,
      update thereafter to form a sliding window of length @n@.
-     It follows the behavior of the slidingWindow function in 
+     It follows the behavior of the slidingWindow function in
      <https://hackage.haskell.org/package/conduit-combinators-1.0.4/docs/Data-Conduit-Combinators.html#v:slidingWindow conduit-combinators>.
 
->>> S.print $ slidingWindow 4 $ S.each "123456"
+>>> S.print $ S.slidingWindow 4 $ S.each "123456"
 fromList "1234"
 fromList "2345"
 fromList "3456"
 
 -}
 
-slidingWindow :: Monad m 
-  => Int 
-  -> Stream (Of a) m b 
+slidingWindow :: Monad m
+  => Int
+  -> Stream (Of a) m b
   -> Stream (Of (Seq.Seq a)) m b
-slidingWindow n = setup (max 1 n :: Int) mempty 
-  where 
-    window !sequ str = do 
-      e <- lift (next str) 
-      case e of 
+slidingWindow n = setup (max 1 n :: Int) mempty
+  where
+    window !sequ str = do
+      e <- lift (next str)
+      case e of
         Left r -> return r
-        Right (a,rest) -> do 
+        Right (a,rest) -> do
           yield (sequ Seq.|> a)
           window (Seq.drop 1 $ sequ Seq.|> a) rest
     setup 0 !sequ str = do
-       yield sequ 
-       window (Seq.drop 1 sequ) str 
-    setup m sequ str = do 
-      e <- lift $ next str 
-      case e of 
+       yield sequ
+       window (Seq.drop 1 sequ) str
+    setup m sequ str = do
+      e <- lift $ next str
+      case e of
         Left r ->  yield sequ >> return r
         Right (x,rest) -> setup (m-1) (sequ Seq.|> x) rest
-{-#INLINABLE slidingWindow #-}
+{-# INLINABLE slidingWindow #-}
 
 -- | Map monadically over a stream, producing a new stream
 --   only containing the 'Just' values.
@@ -2916,8 +2866,8 @@
   loop stream = case stream of
     Return r -> Return r
     Effect m -> Effect (fmap loop m)
-    Step (a :> snext) -> Effect $ do
+    Step (a :> snext) -> Effect $
       flip fmap (phi a) $ \x -> case x of
         Nothing -> loop snext
         Just b -> Step (b :> loop snext)
-{-#INLINABLE mapMaybeM #-}
+{-# INLINABLE mapMaybeM #-}
diff --git a/streaming.cabal b/streaming.cabal
--- a/streaming.cabal
+++ b/streaming.cabal
@@ -1,16 +1,16 @@
 name:                streaming
-version:             0.2.2.0
+version:             0.2.3.0
 cabal-version:       >=1.10
 build-type:          Simple
 synopsis:            an elementary streaming prelude and general stream type.
 
-description:         This package contains two modules, <http://hackage.haskell.org/package/streaming/docs/Streaming.html Streaming> 
+description:         This package contains two modules, <http://hackage.haskell.org/package/streaming/docs/Streaming.html Streaming>
                      and <http://hackage.haskell.org/package/streaming/docs/Streaming-Prelude.html Streaming.Prelude>.
                      The principal module, <http://hackage.haskell.org/package/streaming-0.1.4.3/docs/Streaming-Prelude.html Streaming.Prelude>, exports an elementary streaming prelude focused on
                      a simple \"source\" or \"producer\" type, namely @Stream (Of a) m r@.
                      This is a sort of effectful version of
                      @([a],r)@ in which successive elements of type @a@ arise from some sort of monadic
-                     action before the succession ends with a value of type @r@. 
+                     action before the succession ends with a value of type @r@.
                      Everything in the library is organized to make
                      programming with this type as simple as possible,
                      by the simple expedient of making it as close to @Prelude@
@@ -21,11 +21,11 @@
                      > 1<Enter>
                      > 2<Enter>
                      > 3<Enter>
-                     > 6 :> () 
+                     > 6 :> ()
                      .
                      sums the first three valid integers from user input. Similarly,
                      .
-                     > >>> S.stdoutLn $ S.map (map toUpper) $ S.take 2 S.stdinLn 
+                     > >>> S.stdoutLn $ S.map (map toUpper) $ S.take 2 S.stdinLn
                      > hello<Enter>
                      > HELLO
                      > world!<Enter>
@@ -33,13 +33,13 @@
                      .
                      upper-cases the first two lines from stdin as they arise,
                      and sends them to stdout. And so on,
-                     with filtering, mapping, breaking, chunking, zipping, unzipping, replicating 
-                     and so forth: 
+                     with filtering, mapping, breaking, chunking, zipping, unzipping, replicating
+                     and so forth:
                      we program with streams of @Int@s or @String@s directly as
                      if they constituted something like a list. That's because streams really do constitute something
-                     like a list, and the associated operations can mostly have the same names. 
-                     (A few, like @reverse@, don't stream and thus disappear; 
-                     others like @unzip@ are here given properly streaming formulation for the first time.) 
+                     like a list, and the associated operations can mostly have the same names.
+                     (A few, like @reverse@, don't stream and thus disappear;
+                     others like @unzip@ are here given properly streaming formulation for the first time.)
                      And we everywhere
                      oppose \"extracting a pure list from IO\",
                      which is the origin of typical Haskell memory catastrophes.
@@ -53,7 +53,7 @@
                      .
                      > main = mapM newIORef [1..10^8::Int] >>= mapM readIORef >>= mapM_ print
                      .
-                     The new user notices that this exhausts memory, and worries about the efficiency of Haskell @IORefs@. 
+                     The new user notices that this exhausts memory, and worries about the efficiency of Haskell @IORefs@.
                      But of course it exhausts memory! Look what it says!
                      The problem is immediately cured by writing
                      .
@@ -100,7 +100,7 @@
                      elementary streaming library - since one possesses @Stream ((,) a) m r@
                      or equivalently @Stream (Of a) m r@. This
                      is the type of a \'generator\' or \'producer\' or \'source\' or whatever
-                     you call an effectful stream of items. 
+                     you call an effectful stream of items.
                      /The present Streaming.Prelude is thus the simplest streaming library that can replicate anything like the API of the Prelude and Data.List/.
                      .
                      The emphasis of the library is on interoperation; for
@@ -117,7 +117,7 @@
                      a complex framework, but in a way that integrates transparently with
                      the rest of Haskell, using ideas - e.g. rank 2 types, which are here
                      implicit or explicit in most mapping - that the user can carry elsewhere,
-                     rather than chaining her understanding to the curiosities of 
+                     rather than chaining her understanding to the curiosities of
                      a so-called streaming IO framework (as necessary as that is for certain purposes.)
                      .
                      See the
@@ -186,12 +186,13 @@
 license:             BSD3
 license-file:        LICENSE
 author:              michaelt
-maintainer:          andrew.thaddeus@gmail.com, what_is_it_to_do_anything@yahoo.com
+maintainer:          andrew.thaddeus@gmail.com, chessai1996@gmail.com
 stability:           Experimental
 homepage:            https://github.com/haskell-streaming/streaming
 bug-reports:         https://github.com/haskell-streaming/streaming/issues
 category:            Data, Pipes, Streaming
 extra-source-files:  README.md, changelog.md
+tested-with:         GHC==7.10.3, GHC==8.0.2, GHC==8.2.2, GHC==8.4.4, GHC==8.6.2
 
 source-repository head
     type: git
@@ -203,24 +204,21 @@
     , Streaming.Prelude
     , Streaming.Internal
     , Data.Functor.Of
-  other-extensions:
-      RankNTypes
-    , CPP
-    , StandaloneDeriving
-    , FlexibleContexts
-    , DeriveDataTypeable
-    , DeriveFoldable
-    , DeriveFunctor
-    , DeriveTraversable
-    , UndecidableInstances
   build-depends:
       base >=4.8 && <5
     , mtl >=2.1 && <2.3
     , mmorph >=1.0 && <1.2
-    , semigroups >= 0.18 && <0.19
-    , transformers >=0.5 && <0.6
+    , transformers >=0.4 && <0.6
     , transformers-base < 0.5
     , ghc-prim
     , containers
-  hs-source-dirs:    src
-  default-language:  Haskell2010
+
+  if !impl(ghc >= 8.0)
+    build-depends:
+        fail == 4.9.*
+      , semigroups >= 0.18 && <0.20
+
+  hs-source-dirs:
+    src
+  default-language:
+    Haskell2010
