diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,24 +1,24 @@
-Copyright (c) 2013 Gabriel Gonzalez
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright notice,
-      this list of conditions and the following disclaimer in the documentation
-      and/or other materials provided with the distribution.
-    * Neither the name of Gabriel Gonzalez nor the names of other contributors
-      may be used to endorse or promote products derived from this software
-      without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+Copyright (c) 2013 Gabriel Gonzalez
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * Neither the name of Gabriel Gonzalez nor the names of other contributors
+      may be used to endorse or promote products derived from this software
+      without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,2 +1,2 @@
-import Distribution.Simple
-main = defaultMain
+import Distribution.Simple
+main = defaultMain
diff --git a/pipes-parse.cabal b/pipes-parse.cabal
--- a/pipes-parse.cabal
+++ b/pipes-parse.cabal
@@ -1,37 +1,37 @@
-Name: pipes-parse
-Version: 2.0.1
-Cabal-Version: >=1.8.0.2
-Build-Type: Simple
-License: BSD3
-License-File: LICENSE
-Copyright: 2013 Gabriel Gonzalez
-Author: Gabriel Gonzalez
-Maintainer: Gabriel439@gmail.com
-Bug-Reports: https://github.com/Gabriel439/Haskell-Pipes-Parse-Library/issues
-Synopsis: Parsing infrastructure for the pipes ecosystem
-Description: @pipes-parse@ builds upon the @pipes@ library to provide shared
-    parsing idioms and utilities:
-    .
-    * /Perfect Streaming/: Program in a list-like style in constant memory
-    .
-    * /Leftovers/: Save unused input for later consumption
-    .
-    * /Connect and Resume/: Use @StateT@ to save unused input for later
-    .
-    * /Termination Safety/: Detect and recover from end of input
-    .
-    @Pipes.Parse@ contains the full documentation for this library.
-Category: Control, Pipes, Parsing
-Source-Repository head
-    Type: git
-    Location: https://github.com/Gabriel439/Haskell-Pipes-Parse-Library
-
-Library
-    HS-Source-Dirs: src
-    Build-Depends:
-        base         >= 4       && < 5  ,
-        free         >= 3.1     && < 4.2,
-        pipes        >= 4.0     && < 4.1,
-        transformers >= 0.2.0.0 && < 0.4
-    Exposed-Modules: Pipes.Parse
-    GHC-Options: -O2 -Wall
+Name: pipes-parse
+Version: 2.0.2
+Cabal-Version: >=1.8.0.2
+Build-Type: Simple
+License: BSD3
+License-File: LICENSE
+Copyright: 2013 Gabriel Gonzalez
+Author: Gabriel Gonzalez
+Maintainer: Gabriel439@gmail.com
+Bug-Reports: https://github.com/Gabriel439/Haskell-Pipes-Parse-Library/issues
+Synopsis: Parsing infrastructure for the pipes ecosystem
+Description: @pipes-parse@ builds upon the @pipes@ library to provide shared
+    parsing idioms and utilities:
+    .
+    * /Perfect Streaming/: Program in a list-like style in constant memory
+    .
+    * /Leftovers/: Save unused input for later consumption
+    .
+    * /Connect and Resume/: Use @StateT@ to save unused input for later
+    .
+    * /Termination Safety/: Detect and recover from end of input
+    .
+    @Pipes.Parse@ contains the full documentation for this library.
+Category: Control, Pipes, Parsing
+Source-Repository head
+    Type: git
+    Location: https://github.com/Gabriel439/Haskell-Pipes-Parse-Library
+
+Library
+    HS-Source-Dirs: src
+    Build-Depends:
+        base         >= 4       && < 5  ,
+        free         >= 3.1     && < 5  ,
+        pipes        >= 4.0     && < 4.1,
+        transformers >= 0.2.0.0 && < 0.4
+    Exposed-Modules: Pipes.Parse
+    GHC-Options: -O2 -Wall
diff --git a/src/Pipes/Parse.hs b/src/Pipes/Parse.hs
--- a/src/Pipes/Parse.hs
+++ b/src/Pipes/Parse.hs
@@ -1,407 +1,409 @@
-{-|
-    Element-agnostic parsing utilities for @pipes@
-
-    @pipes-parse@ provides two ways to parse and transform streams in constant
-    space:
-
-    * The \"list-like\" approach, using the split \/ transform \/ join paradigm
-
-    * The monadic approach, using parser combinators
-
-    The top half of this module provides the list-like approach, which is easier
-    to use, but less powerful.  The key idea is that:
-
-> -- '~' means "is analogous to"
-> Producer a m ()            ~   [a]
->
-> FreeT (Producer a m) m ()  ~  [[a]]
-
-    'FreeT' nests each subsequent 'Producer' within the return value of the
-    previous 'Producer' so that you cannot access the next 'Producer' until you
-    completely drain the current 'Producer'.  However, you rarely need to work
-    with 'FreeT' directly.  Instead, you structure everything using
-    \"splitters\", \"transformations\" and \"joiners\":
-
-> -- A "splitter"
-> Producer a m ()           -> FreeT (Producer a m) m ()  ~   [a]  -> [[a]]
->
-> -- A "transformation"
-> FreeT (Producer a m) m () -> FreeT (Producer a m) m ()  ~  [[a]] -> [[a]]
->
-> -- A "joiner"
-> FreeT (Producer a m) m () -> Producer a m ()            ~  [[a]] ->  [a]
-
-    For example, if you wanted to group standard input by equal lines and take
-    the first three groups, you would write:
-
-> import Pipes
-> import qualified Pipes.Parse as Parse
-> import qualified Pipes.Prelude as Prelude
->
-> threeGroups :: (Monad m, Eq a) => Producer a m () -> Producer a m ()
-> threeGroups = Parse.concat . Parse.takeFree 3 . Parse.groupBy (==)
-> --            ^ Joiner       ^ Transformation   ^ Splitter
-
-    This then limits standard input to the first three consecutive groups of
-    equal lines:
-
->>> runEffect $ threeGroups Prelude.stdinLn >-> Prelude.stdoutLn
-Group1<Enter>
-Group1
-Group1<Enter>
-Group1
-Group2<Enter>
-Group2
-Group3<Enter>
-Group3
-Group3<Enter>
-Group3
-Group4<Enter>
->>> -- Done, because we began entering our fourth group
-
-    The advantage of this style or programming is that you never bring more than
-    a single element into memory.  This works because `FreeT` sub-divides the
-    `Producer` without concatenating elements together, preserving the laziness
-    of the underlying 'Producer'.
-
-    The bottom half of this module lets you implement your own list-like
-    transformations using monadic parsers.
-
-    For example, if you wanted to repeatedly sum every 3 elements and yield the
-    result, you would write:
-
-> import Control.Monad (unless)
-> import Pipes
-> import qualified Pipes.Prelude as P
-> import Pipes.Parse
->
-> sum3 :: (Monad m, Num a) => Producer a (StateT (Producer a m ()) m) ()
-> sum3 = do
->     eof <- lift isEndOfInput
->     unless eof $ do
->         n <- lift $ P.sum (input >-> P.take 3)
->         yield n
->         sum3
-
-    When you are done building the parser, you convert your parser to a
-    list-like function using `evalStateP`:
-
-> import Pipes.Lift (evalStateP)
->
-> -- sum3'  ~  (Num a) => [a] -> [a]
->
-> sum3' :: (Monad m, Num a) => Producer a m () -> Producer a m ()
-> sum3' p = evalStateP p sum3
-
-    ... then apply it to the `Producer` you want to transform:
-
->>> runEffect $ sum3' (P.readLn >-> P.takeWhile (/= 0)) >-> P.print
-1<Enter>
-4<Enter>
-5<Enter>
-10
-2<Enter>
-0<Enter>
-2
->>>
-
--}
-
-{-# LANGUAGE RankNTypes #-}
-
-module Pipes.Parse (
-    -- * Splitters
-    groupBy,
-    chunksOf,
-    splitOn,
-
-    -- * Transformations
-    takeFree,
-    dropFree,
-
-    -- * Joiners
-    concat,
-    intercalate,
-
-    -- * Low-level Parsers
-    -- $lowlevel
-    draw,
-    unDraw,
-    peek,
-    isEndOfInput,
-
-    -- * High-level Parsers
-    -- $highlevel
-    input,
-
-    -- * Utilities
-    takeWhile,
-
-    -- * Re-exports
-    -- $reexports
-    module Control.Monad.Trans.Free,
-    module Control.Monad.Trans.State.Strict
-    ) where
-
-import Control.Applicative ((<$>), (<$))
-import qualified Control.Monad.Trans.Free as F
-import Control.Monad.Trans.Free (FreeF(Pure, Free), FreeT(FreeT, runFreeT))
-import qualified Control.Monad.Trans.State.Strict as S
-import Control.Monad.Trans.State.Strict (
-    StateT(StateT, runStateT), evalStateT, execStateT )
-import Pipes
-import Pipes.Lift (runStateP)
-import qualified Pipes.Prelude as P
-import Prelude hiding (concat, takeWhile)
-
-{-| Split a 'Producer' into a `FreeT`-delimited stream of 'Producer's grouped by
-    the supplied equality predicate
--}
-groupBy
-    :: (Monad m)
-    => (a -> a -> Bool) -> Producer a m r -> FreeT (Producer a m) m r
-groupBy equal = loop
-  where
-    loop p = do
-        (x, p') <- F.liftF $ runStateP p $ do
-            x <- lift draw
-            case x of
-                Left  r -> return (Just r)
-                Right a -> do
-                    yield a
-                    (Just <$> input) >-> (Nothing <$ takeWhile (equal a))
-        case x of
-            Just r  -> return r
-            Nothing -> loop p'
-{-# INLINABLE groupBy #-}
-
-{-| Split a 'Producer' into a `FreeT`-delimited stream of 'Producer's of the
-    given chunk size
--}
-chunksOf :: (Monad m) => Int -> Producer a m r -> FreeT (Producer a m) m r
-chunksOf n = loop
-  where
-    loop p = do
-        (x, p') <- F.liftF $ runStateP p $
-            (Just <$> input) >-> (Nothing <$ P.take n)
-        case x of
-            Just r  -> return r
-            Nothing -> loop p'
-{-# INLINABLE chunksOf #-}
-
-{-| Split a 'Producer' into a `FreeT`-delimited stream of 'Producer's separated
-    by elements that satisfy the given predicate
--}
-splitOn
-    :: (Monad m) => (a -> Bool) -> Producer a m r -> FreeT (Producer a m) m r
-splitOn predicate = loop
-  where
-    loop p = do
-        (x, p') <- F.liftF $ runStateP p $
-            (Just <$> input) >-> (Nothing <$ takeWhile (not . predicate))
-        case x of
-            Just r  -> return r
-            Nothing -> loop p'
-{-# INLINABLE splitOn #-}
-
--- | Join a 'FreeT'-delimited stream of 'Producer's into a single 'Producer'
-concat :: (Monad m) => FreeT (Producer a m) m r -> Producer a m r
-concat = loop
-  where
-    loop f = do
-        x <- lift (runFreeT f)
-        case x of
-            Pure r -> return r
-            Free p -> do
-                f' <- p
-                loop f'
-{-# INLINABLE concat #-}
-
-{-| Join a 'FreeT'-delimited stream of 'Producer's into a single 'Producer' by
-    intercalating a 'Producer' in between them
--}
-intercalate
-    :: (Monad m)
-    => Producer a m () -> FreeT (Producer a m) m r -> Producer a m r
-intercalate sep = go0
-  where
-    go0 f = do
-        x <- lift (runFreeT f)
-        case x of
-            Pure r -> return r
-            Free p -> do
-                f' <- p
-                go1 f'
-    go1 f = do
-        x <- lift (runFreeT f)
-        case x of
-            Pure r -> return r
-            Free p -> do
-                sep
-                f' <- p
-                go1 f'
-{-# INLINABLE intercalate #-}
-
--- | @(takeFree n)@ only keeps the first @n@ functor layers of a 'FreeT'
-takeFree :: (Functor f, Monad m) => Int -> FreeT f m () -> FreeT f m ()
-takeFree = go
-  where
-    go n f =
-        if (n > 0)
-        then FreeT $ do
-            x <- runFreeT f
-            case x of
-                Pure () -> return (Pure ())
-                Free w  -> return (Free (fmap (go $! n - 1) w))
-        else return ()
-{-# INLINABLE takeFree #-}
-
-{-| @(dropFree n)@ peels off the first @n@ layers of a 'FreeT'
-
-    Use carefully: the peeling off is not free.   This runs the first @n@
-    layers, just discarding everything they produce.
--}
-dropFree
-    :: (Monad m) => Int -> FreeT (Producer a m) m r -> FreeT (Producer a m) m r
-dropFree = go
-  where
-    go n ft
-        | n <= 0 = ft
-        | otherwise = FreeT $ do
-            ff <- runFreeT ft
-            case ff of
-                Pure _ -> return ff
-                Free f -> do
-                    ft' <- runEffect $ for f discard
-                    runFreeT $ go (n-1) ft'
-{-# INLINABLE dropFree #-}
-
-{- $lowlevel
-    @pipes-parse@ handles end-of-input and pushback by storing a 'Producer' in
-    a 'StateT' layer.
--}
-
-{-| Draw one element from the underlying 'Producer', returning 'Left' if the
-    'Producer' is empty
--}
-draw :: (Monad m) => StateT (Producer a m r) m (Either r a)
-draw = do
-    p <- S.get
-    x <- lift (next p)
-    case x of
-        Left   r      -> do
-            S.put (return r)
-            return (Left r)
-        Right (a, p') -> do
-            S.put p'
-            return (Right a)
-{-# INLINABLE draw #-}
-
--- | Push back an element onto the underlying 'Producer'
-unDraw :: (Monad m) => a -> StateT (Producer a m r) m ()
-unDraw a = S.modify (yield a >>)
-{-# INLINABLE unDraw #-}
-
-{-| 'peek' checks the first element of the stream, but uses 'unDraw' to push the
-    element back so that it is available for the next 'draw' command.
-
-> peek = do
->     x <- draw
->     case x of
->         Left  _ -> return ()
->         Right a -> unDraw a
->     return x
--}
-peek :: (Monad m) => StateT (Producer a m r) m (Either r a)
-peek = do
-    x <- draw
-    case x of
-        Left  _ -> return ()
-        Right a -> unDraw a
-    return x
-{-# INLINABLE peek #-}
-
-{-| Check if the underlying 'Producer' is empty
-
-> isEndOfInput = liftM isLeft peek
--}
-isEndOfInput :: (Monad m) => StateT (Producer a m r) m Bool
-isEndOfInput = do
-    x <- peek
-    return (case x of
-        Left  _ -> True
-        Right _ -> False )
-{-# INLINABLE isEndOfInput #-}
-
-{- $highlevel
-    'input' provides a 'Producer' that streams from the underlying 'Producer'.
-
-    Streaming from 'input' differs from streaming directly from the underlying
-    'Producer' because any unused input is saved for later, as the following
-    example illustrates:
-
-> import Control.Monad.Trans.State.Strict
-> import Pipes
-> import Pipes.Parse
-> import qualified Pipes.Prelude as P
->
-> parser :: (Show a) => StateT (Producer a IO ()) IO ()
-> parser = do
->     runEffect $ input >-> P.take 2 >-> P.show >-> P.stdoutLn
->
->     liftIO $ putStrLn "Intermission"
->
->     runEffect $ input >-> P.take 2 >-> P.show >-> P.stdoutLn
-
-    The second pipeline resumes where the first pipeline left off:
-
->>> evalStateT parser (each [1..])
-1
-2
-Intermission
-3
-4
-
-    You can see more examples of how to use these parsing utilities by studying
-    the source code for the above splitters.
--}
-
-{-| Stream from the underlying 'Producer'
-
-    'input' terminates if the 'Producer' is empty, returning the final return
-    value of the 'Producer'.
--}
-input :: (Monad m) => Producer' a (StateT (Producer a m r) m) r
-input = loop
-  where
-    loop = do
-        x <- lift draw
-        case x of
-            Left  r -> return r
-            Right a -> do
-                yield a
-                loop
-{-# INLINABLE input #-}
-
-{-| A variation on 'Pipes.Prelude.takeWhile' from @Pipes.Prelude@ that 'unDraw's
-    the first element that does not match
--}
-takeWhile
-    :: (Monad m) => (a -> Bool) -> Pipe a a (StateT (Producer a m r) m) ()
-takeWhile predicate = loop
-  where
-    loop = do
-        a <- await
-        if (predicate a)
-            then do
-                yield a
-                loop
-            else lift (unDraw a)
-{-# INLINABLE takeWhile #-}
-
-{- $reexports
-    @Control.Monad.Trans.Free@ re-exports 'FreeF', 'FreeT', and 'runFreeT'.
-
-    @Control.Monad.Trans.State.Strict@ re-exports 'StateT', 'runStateT',
-    'evalStateT', and 'execStateT'.
--}
+{-|
+    Element-agnostic parsing utilities for @pipes@
+
+    @pipes-parse@ provides two ways to parse and transform streams in constant
+    space:
+
+    * The \"list-like\" approach, using the split \/ transform \/ join paradigm
+
+    * The monadic approach, using parser combinators
+
+    The top half of this module provides the list-like approach, which is easier
+    to use, but less powerful.  The key idea is that:
+
+> -- '~' means "is analogous to"
+> Producer a m ()            ~   [a]
+>
+> FreeT (Producer a m) m ()  ~  [[a]]
+
+    'FreeT' nests each subsequent 'Producer' within the return value of the
+    previous 'Producer' so that you cannot access the next 'Producer' until you
+    completely drain the current 'Producer'.  However, you rarely need to work
+    with 'FreeT' directly.  Instead, you structure everything using
+    \"splitters\", \"transformations\" and \"joiners\":
+
+> -- A "splitter"
+> Producer a m ()           -> FreeT (Producer a m) m ()  ~   [a]  -> [[a]]
+>
+> -- A "transformation"
+> FreeT (Producer a m) m () -> FreeT (Producer a m) m ()  ~  [[a]] -> [[a]]
+>
+> -- A "joiner"
+> FreeT (Producer a m) m () -> Producer a m ()            ~  [[a]] ->  [a]
+
+    For example, if you wanted to group standard input by equal lines and take
+    the first three groups, you would write:
+
+> import Pipes
+> import qualified Pipes.Parse as Parse
+> import qualified Pipes.Prelude as Prelude
+>
+> threeGroups :: (Monad m, Eq a) => Producer a m () -> Producer a m ()
+> threeGroups = Parse.concat . Parse.takeFree 3 . Parse.groupBy (==)
+> --            ^ Joiner       ^ Transformation   ^ Splitter
+
+    This then limits standard input to the first three consecutive groups of
+    equal lines:
+
+>>> runEffect $ threeGroups Prelude.stdinLn >-> Prelude.stdoutLn
+Group1<Enter>
+Group1
+Group1<Enter>
+Group1
+Group2<Enter>
+Group2
+Group3<Enter>
+Group3
+Group3<Enter>
+Group3
+Group4<Enter>
+>>> -- Done, because we began entering our fourth group
+
+    The advantage of this style or programming is that you never bring more than
+    a single element into memory.  This works because `FreeT` sub-divides the
+    `Producer` without concatenating elements together, preserving the laziness
+    of the underlying 'Producer'.
+
+    The bottom half of this module lets you implement your own list-like
+    transformations using monadic parsers.
+
+    For example, if you wanted to repeatedly sum every 3 elements and yield the
+    result, you would write:
+
+> import Control.Monad (unless)
+> import Pipes
+> import qualified Pipes.Prelude as P
+> import Pipes.Parse
+>
+> sum3 :: (Monad m, Num a) => Producer a (StateT (Producer a m ()) m) ()
+> sum3 = do
+>     eof <- lift isEndOfInput
+>     unless eof $ do
+>         n <- lift $ P.sum (input >-> P.take 3)
+>         yield n
+>         sum3
+
+    When you are done building the parser, you convert your parser to a
+    list-like function using `evalStateP`:
+
+> import Pipes.Lift (evalStateP)
+>
+> -- sum3'  ~  (Num a) => [a] -> [a]
+>
+> sum3' :: (Monad m, Num a) => Producer a m () -> Producer a m ()
+> sum3' p = evalStateP p sum3
+
+    ... then apply it to the `Producer` you want to transform:
+
+>>> runEffect $ sum3' (P.readLn >-> P.takeWhile (/= 0)) >-> P.print
+1<Enter>
+4<Enter>
+5<Enter>
+10
+2<Enter>
+0<Enter>
+2
+>>>
+
+-}
+
+{-# LANGUAGE RankNTypes #-}
+
+module Pipes.Parse (
+    -- * Splitters
+    groupBy,
+    chunksOf,
+    splitOn,
+
+    -- * Transformations
+    takeFree,
+    dropFree,
+
+    -- * Joiners
+    concat,
+    intercalate,
+
+    -- * Low-level Parsers
+    -- $lowlevel
+    draw,
+    unDraw,
+    peek,
+    isEndOfInput,
+
+    -- * High-level Parsers
+    -- $highlevel
+    input,
+
+    -- * Utilities
+    takeWhile,
+
+    -- * Re-exports
+    -- $reexports
+    module Control.Monad.Trans.Free,
+    module Control.Monad.Trans.State.Strict
+    ) where
+
+import Control.Applicative ((<$>), (<$))
+import Control.Monad (void)
+import qualified Control.Monad.Trans.Free as F
+import Control.Monad.Trans.Free (FreeF(Pure, Free), FreeT(FreeT, runFreeT))
+import qualified Control.Monad.Trans.State.Strict as S
+import Control.Monad.Trans.State.Strict (
+    StateT(StateT, runStateT), evalStateT, execStateT )
+import Pipes
+import Pipes.Lift (runStateP)
+import qualified Pipes.Prelude as P
+import Prelude hiding (concat, takeWhile)
+
+{-| Split a 'Producer' into a `FreeT`-delimited stream of 'Producer's grouped by
+    the supplied equality predicate
+-}
+groupBy
+    :: (Monad m)
+    => (a -> a -> Bool) -> Producer a m r -> FreeT (Producer a m) m r
+groupBy equal = loop
+  where
+    loop p = do
+        (x, p') <- F.liftF $ runStateP p $ do
+            x <- lift draw
+            case x of
+                Left  r -> return (Just r)
+                Right a -> do
+                    yield a
+                    (Just <$> input) >-> (Nothing <$ takeWhile (equal a))
+        case x of
+            Just r  -> return r
+            Nothing -> loop p'
+{-# INLINABLE groupBy #-}
+
+{-| Split a 'Producer' into a `FreeT`-delimited stream of 'Producer's of the
+    given chunk size
+-}
+chunksOf :: (Monad m) => Int -> Producer a m r -> FreeT (Producer a m) m r
+chunksOf n = loop
+  where
+    loop p = do
+        (x, p') <- F.liftF $ runStateP p $
+            (Just <$> input) >-> (Nothing <$ P.take n)
+        case x of
+            Just r  -> return r
+            Nothing -> loop p'
+{-# INLINABLE chunksOf #-}
+
+{-| Split a 'Producer' into a `FreeT`-delimited stream of 'Producer's separated
+    by elements that satisfy the given predicate
+-}
+splitOn
+    :: (Monad m) => (a -> Bool) -> Producer a m r -> FreeT (Producer a m) m r
+splitOn predicate = go
+  where
+    go p = do
+        (x, p') <- F.liftF $ runStateP p $ do
+            void input >-> takeWhile (not . predicate)
+            lift draw
+        case x of
+            Left  r -> return r
+            Right _ -> go p'
+{-# INLINABLE splitOn #-}
+
+-- | Join a 'FreeT'-delimited stream of 'Producer's into a single 'Producer'
+concat :: (Monad m) => FreeT (Producer a m) m r -> Producer a m r
+concat = loop
+  where
+    loop f = do
+        x <- lift (runFreeT f)
+        case x of
+            Pure r -> return r
+            Free p -> do
+                f' <- p
+                loop f'
+{-# INLINABLE concat #-}
+
+{-| Join a 'FreeT'-delimited stream of 'Producer's into a single 'Producer' by
+    intercalating a 'Producer' in between them
+-}
+intercalate
+    :: (Monad m)
+    => Producer a m () -> FreeT (Producer a m) m r -> Producer a m r
+intercalate sep = go0
+  where
+    go0 f = do
+        x <- lift (runFreeT f)
+        case x of
+            Pure r -> return r
+            Free p -> do
+                f' <- p
+                go1 f'
+    go1 f = do
+        x <- lift (runFreeT f)
+        case x of
+            Pure r -> return r
+            Free p -> do
+                sep
+                f' <- p
+                go1 f'
+{-# INLINABLE intercalate #-}
+
+-- | @(takeFree n)@ only keeps the first @n@ functor layers of a 'FreeT'
+takeFree :: (Functor f, Monad m) => Int -> FreeT f m () -> FreeT f m ()
+takeFree = go
+  where
+    go n f =
+        if (n > 0)
+        then FreeT $ do
+            x <- runFreeT f
+            case x of
+                Pure () -> return (Pure ())
+                Free w  -> return (Free (fmap (go $! n - 1) w))
+        else return ()
+{-# INLINABLE takeFree #-}
+
+{-| @(dropFree n)@ peels off the first @n@ layers of a 'FreeT'
+
+    Use carefully: the peeling off is not free.   This runs the first @n@
+    layers, just discarding everything they produce.
+-}
+dropFree
+    :: (Monad m) => Int -> FreeT (Producer a m) m r -> FreeT (Producer a m) m r
+dropFree = go
+  where
+    go n ft
+        | n <= 0 = ft
+        | otherwise = FreeT $ do
+            ff <- runFreeT ft
+            case ff of
+                Pure _ -> return ff
+                Free f -> do
+                    ft' <- runEffect $ for f discard
+                    runFreeT $ go (n-1) ft'
+{-# INLINABLE dropFree #-}
+
+{- $lowlevel
+    @pipes-parse@ handles end-of-input and pushback by storing a 'Producer' in
+    a 'StateT' layer.
+-}
+
+{-| Draw one element from the underlying 'Producer', returning 'Left' if the
+    'Producer' is empty
+-}
+draw :: (Monad m) => StateT (Producer a m r) m (Either r a)
+draw = do
+    p <- S.get
+    x <- lift (next p)
+    case x of
+        Left   r      -> do
+            S.put (return r)
+            return (Left r)
+        Right (a, p') -> do
+            S.put p'
+            return (Right a)
+{-# INLINABLE draw #-}
+
+-- | Push back an element onto the underlying 'Producer'
+unDraw :: (Monad m) => a -> StateT (Producer a m r) m ()
+unDraw a = S.modify (yield a >>)
+{-# INLINABLE unDraw #-}
+
+{-| 'peek' checks the first element of the stream, but uses 'unDraw' to push the
+    element back so that it is available for the next 'draw' command.
+
+> peek = do
+>     x <- draw
+>     case x of
+>         Left  _ -> return ()
+>         Right a -> unDraw a
+>     return x
+-}
+peek :: (Monad m) => StateT (Producer a m r) m (Either r a)
+peek = do
+    x <- draw
+    case x of
+        Left  _ -> return ()
+        Right a -> unDraw a
+    return x
+{-# INLINABLE peek #-}
+
+{-| Check if the underlying 'Producer' is empty
+
+> isEndOfInput = liftM isLeft peek
+-}
+isEndOfInput :: (Monad m) => StateT (Producer a m r) m Bool
+isEndOfInput = do
+    x <- peek
+    return (case x of
+        Left  _ -> True
+        Right _ -> False )
+{-# INLINABLE isEndOfInput #-}
+
+{- $highlevel
+    'input' provides a 'Producer' that streams from the underlying 'Producer'.
+
+    Streaming from 'input' differs from streaming directly from the underlying
+    'Producer' because any unused input is saved for later, as the following
+    example illustrates:
+
+> import Control.Monad.Trans.State.Strict
+> import Pipes
+> import Pipes.Parse
+> import qualified Pipes.Prelude as P
+>
+> parser :: (Show a) => StateT (Producer a IO ()) IO ()
+> parser = do
+>     runEffect $ input >-> P.take 2 >-> P.show >-> P.stdoutLn
+>
+>     liftIO $ putStrLn "Intermission"
+>
+>     runEffect $ input >-> P.take 2 >-> P.show >-> P.stdoutLn
+
+    The second pipeline resumes where the first pipeline left off:
+
+>>> evalStateT parser (each [1..])
+1
+2
+Intermission
+3
+4
+
+    You can see more examples of how to use these parsing utilities by studying
+    the source code for the above splitters.
+-}
+
+{-| Stream from the underlying 'Producer'
+
+    'input' terminates if the 'Producer' is empty, returning the final return
+    value of the 'Producer'.
+-}
+input :: (Monad m) => Producer' a (StateT (Producer a m r) m) r
+input = loop
+  where
+    loop = do
+        x <- lift draw
+        case x of
+            Left  r -> return r
+            Right a -> do
+                yield a
+                loop
+{-# INLINABLE input #-}
+
+{-| A variation on 'Pipes.Prelude.takeWhile' from @Pipes.Prelude@ that 'unDraw's
+    the first element that does not match
+-}
+takeWhile
+    :: (Monad m) => (a -> Bool) -> Pipe a a (StateT (Producer a m r) m) ()
+takeWhile predicate = loop
+  where
+    loop = do
+        a <- await
+        if (predicate a)
+            then do
+                yield a
+                loop
+            else lift (unDraw a)
+{-# INLINABLE takeWhile #-}
+
+{- $reexports
+    @Control.Monad.Trans.Free@ re-exports 'FreeF', 'FreeT', and 'runFreeT'.
+
+    @Control.Monad.Trans.State.Strict@ re-exports 'StateT', 'runStateT',
+    'evalStateT', and 'execStateT'.
+-}
