main 3997b02a5e22 cached
22 files
232.3 KB
67.4k tokens
1 requests
Download .txt
Showing preview only (241K chars total). Download the full file or copy to clipboard to get everything.
Repository: Gabriel439/Haskell-Pipes-Library
Branch: main
Commit: 3997b02a5e22
Files: 22
Total size: 232.3 KB

Directory structure:
gitextract_l6xj46in/

├── .github/
│   └── workflows/
│       └── haskell.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── Setup.hs
├── benchmarks/
│   ├── Common.hs
│   ├── LiftBench.hs
│   └── PreludeBench.hs
├── laws.md
├── nix/
│   └── .gitkeep
├── pipes.cabal
├── release.nix
├── shell.nix
├── src/
│   ├── Pipes/
│   │   ├── Core.hs
│   │   ├── Internal.hs
│   │   ├── Lift.hs
│   │   ├── Prelude.hs
│   │   └── Tutorial.hs
│   └── Pipes.hs
├── stack.yaml
└── tests/
    └── Main.hs

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/haskell.yml
================================================
name: Haskell CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - uses: haskell/actions/setup@v1.2
    - name: Cache
      uses: actions/cache@v1
      env:
        cache-name: cache-cabal
      with:
        path: ~/.cabal
        key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/*.cabal') }}-${{ hashFiles('**/cabal.project') }}
        restore-keys: |
          ${{ runner.os }}-build-${{ env.cache-name }}-
          ${{ runner.os }}-build-
          ${{ runner.os }}-

    - name: Install dependencies
      run: |
        cabal update
        cabal build --only-dependencies --enable-tests --enable-benchmarks
    - name: Build
      run: cabal build --enable-tests --enable-benchmarks all
    - name: Run tests
      run: cabal test all


================================================
FILE: .gitignore
================================================
cabal-dev
.cabal-sandbox
cabal.sandbox.config
dist
.stack-work


================================================
FILE: CHANGELOG.md
================================================
4.3.16

* Fix example code for `every`
* Improved documentation for `ListT`

4.3.15

* Build against `ghc-9.0`

4.3.14

* Add `mapMaybe` and `wither`, and more laws for `filter` and `filterM`.

4.3.13

* Add `MonadFail` instance for `Proxy`

4.3.12

* Fix space leak introduced in version 4.3.10
    * This leak primarily affects the use of `forever`

4.3.11

* Fix documentation for `scanM`

4.3.10

* Relax `Monad` constraints to `Functor`
* Support GHC 8.8

4.3.9

* Increase upper bound on `exceptions`

4.3.8

* Increase upper bound on `exceptions`

4.3.7

* Documentation fix

4.3.6

* Fix implementation of `pass` in `MonadWriter` instance for `Proxy`

4.3.5

* Support `Semigroup` being a super-class of `Monoid`

4.3.4

* Increase upper bound on `mmorph`

4.3.3

* Make `X` a synonym for `Data.Void.Void`

4.3.2

* BUG FIX: Fix `MMonad` instance for `ListT`
    * The old instance was an infinite loop

4.3.1

* Support building against `ghc-7.4`

4.3.0

* BREAKING CHANGE: Remove `Alternative`/`MonadPlus` instances for `Proxy`
    * See commit 08e7302f43dbf2a40bd367c5ee73ee3367e17768 which explains why
* Add `Traversable` instance for `ListT`
* New `MonadThrow`/`MonadCatch`/`MMonad`/`Semigroup`/`MonadZip` instances for
  `ListT`
* New `MonadThrow`/`MonadCatch` instances for `Proxy`
* Fix lower bound on `mtl`
* Increase upper bound on `optparse-applicative`

4.2.0

* BREAKING CHANGE: Switch from `ErrorT` to `ExceptT`
* Add `Foldable` instance for `ListT`
* Fix all warnings
* Enable foldr/build fusion for `toList`

4.1.9

* Increase lower bound on `criterion`
* Increase upper bound on `transformers` for tests/benchmarks
* Optimize code by delaying `INLINABLE` annotations

4.1.8

* Increase upper bound on `transformers`
* Prepare for MRP (Monad of no Return Proposal)

4.1.7

* Increase lower bound on `deepseq`
* Add `unfoldr`
* Add `loop`
* Add `toListM'`
* Improve efficiency of `drop`
* License tutorial under Creative Commons license

4.1.6

* Increase lower bound on `base`
* Add diagrams to `Pipes.Core` documentation
* Add `mapM_`
* Add `takeWhile'`
* Add `seq`
* Improve efficiency of `toListM`

4.1.5

* Increase upper bound on `criterion`

4.1.4

* Increase upper bound on `criterion`
* Add `Monoid` instance for `Proxy`

4.1.3

* Increase lower bound on `mtl`
* Re-export `void`
* Add `fold'`
* Add `foldM'`

4.1.2

* Increase upper bounds on `transformers` and `mtl`

4.1.1

* Add `runListT`
* Add `MMonad` instance for `Proxy`
* Add `repeatM`
* Add laws to documentation of `Pipes.Prelude` utilities

4.1.0

* Remove Haskell98 support
* Use internal `X` type instead of `Data.Void`
* Document `Pipes.Lift` module:w
* Add `drain`
* Add `sequence`

4.0.2

* Improve performance of `each`
* Add tutorial appendix explaining how to work around quadratic time complexity

4.0.1

* Remove `WriterT` and `RWST` benchmarks
* Add `Enumerable` instance for `ErrorT`
* Add cabal flag for Haskell98 compilation
* Add several rewrite rules
* Add `mtl` instances for `ListT`
* Fix implementation of `pass`, which did not satisfy `Writer` laws
* Implement `fail` for `ListT`
* Add type synonym table to tutorial appendix
* Add QuickCheck tests for `pipes` laws
* Add `mapFoldable`
* Add `Monoid` instance for `ListT`
* Add manual proofs of `pipes` laws in `laws.md`

4.0.0

Major upgrade of `pipes` to no longer use `Proxy` type class


================================================
FILE: LICENSE
================================================
Copyright (c) 2012-2016 Gabriella 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 Gabriella 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.


================================================
FILE: README.md
================================================
# `pipes`

`pipes` is a clean and powerful stream processing library that lets you build
and connect reusable streaming components.

## Quick start

* Install the [Haskell Platform](http://www.haskell.org/platform/)
* `cabal install pipes`

Then fire up `ghci`:

    $ ghci
    Prelude> import Pipes
    Prelude Pipes> import qualified Pipes.Prelude as P

... and echo standard input to standard output until you enter `quit`.

    Prelude Pipes P> runEffect $ P.stdinLn >-> P.takeWhile (/= "quit") >-> P.stdoutLn
    Test[Enter]
    Test
    Apple[Enter]
    Apple
    quit[Enter]
    Prelude P> -- Done!

To learn more, read the
[pipes tutorial](http://hackage.haskell.org/package/pipes/docs/Pipes-Tutorial.html).

## Features

* *Concise API*: Use simple commands like `for`, `(>->)`, `await`, and `yield`

* *Blazing fast*: Implementation tuned for speed, including shortcut fusion

* *Lightweight Dependency*: `pipes` is small and compiles very rapidly,
  including dependencies

* *Elegant semantics*: Use practical category theory

* *ListT*: Correct implementation of `ListT` that interconverts with pipes

* *Bidirectionality*: Implement duplex channels

* *Extensive Documentation*: Second to none!

## Philosophy

The `pipes` library emphasizes the following three design precepts:

* Emphasize elegance - Elegant libraries replace inelegant libraries

* Theory everywhere - Principled design promotes intuitive behavior

* Minimize dependencies - Small dependency profiles maximize portability

## Outline

The core `pipes` ecosystem consists of the following four libraries:

* `pipes`: The elegant, theoretically-principled core.

* `pipes-concurrency`: Message passing and reactive programming

* `pipes-parse`: Utilities for parsing streams

* `pipes-safe`: Resource management and exception safety

These represent the core areas that I envision for `pipes`.  The latter three
libraries represent the more pragmatic face of the ecosystem and make design
tradeoffs where there is no known elegant solution.

Derived libraries that build on top of these include:

* `pipes-network` and `pipes-network-tls`: Networking support

* `pipes-attoparsec`: High-efficiency streaming parsing

* `pipes-zlib`: Compression and decompression

* `pipes-binary`: Streaming serialization and deserialization

* `pipes-aeson`: Streaming JSON encoding and decoding

## Development Status

[![Build Status](https://travis-ci.org/Gabriella439/Haskell-Pipes-Library.png)](https://travis-ci.org/Gabriella439/Haskell-Pipes-Library)

`pipes` is stable, and current work focuses on packaging `pipes` for various
package managers.  The long term goal is to get `pipes` into the Haskell
platform and become the basic building block for streaming APIs.

## Community Resources

* [Haskell wiki page](http://www.haskell.org/haskellwiki/Pipes)

* [Mailing list](mailto:haskell-pipes@googlegroups.com) ([Google Group](https://groups.google.com/forum/?fromgroups#!forum/haskell-pipes))

## How to contribute

* Contribute code

* Build derived libraries

* Write `pipes` tutorials

## License (BSD 3-clause)

Copyright (c) 2012-2014 Gabriella 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 Gabriella 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.


================================================
FILE: Setup.hs
================================================
import Distribution.Simple
main = defaultMain


================================================
FILE: benchmarks/Common.hs
================================================
module Common (commonMain) where

import Criterion.Main (Benchmark, runMode)
import Criterion.Main.Options as Criterion
import Data.Maybe (fromMaybe)
import Data.Monoid
import Options.Applicative

commonMain :: Int                    -- ^ default maximum data size
           -> (Int -> [Benchmark])   -- ^ the benchmarks to run
           -> IO ()
commonMain mdMax bench = do
    (maybeNewMax, critMode) <- execParser $ info (helper <*> options) mempty
    runMode critMode $ bench (fromMaybe mdMax maybeNewMax)

options :: Parser (Maybe Int, Criterion.Mode)
options =
    (,) <$> optional (option auto (help "benchmark maximum data size"
                                   <> metavar "N" <> short 'i'  <> long "imax"))
        <*> Criterion.parseWith Criterion.defaultConfig


================================================
FILE: benchmarks/LiftBench.hs
================================================
{-# LANGUAGE RankNTypes #-}
module Main (main) where

import Common (commonMain)
import Control.Monad.Identity
import qualified Control.Monad.Trans.Reader as R
import qualified Control.Monad.Trans.State.Strict as S
import Criterion.Main
import Data.Monoid
import Pipes
import Pipes.Lift

defaultMax :: Int
defaultMax = 10000

main :: IO ()
main = commonMain defaultMax liftBenchmarks

iter :: forall m a . (Monad m , Ord a, Num a) => (a -> m a) -> a -> Effect m a
iter a vmax = loop 0
    where
        loop n
            | n > vmax  = return vmax
            | otherwise = do
                x <- lift $ a n
                loop $! x

s_bench :: Int -> Effect (S.StateT Int Identity) Int
s_bench = iter (\n -> S.get >>= (\a -> S.put $! a + n) >> return (n + 1))

r_bench :: Int -> Effect (R.ReaderT Int Identity) Int
r_bench = iter (\n -> R.ask >>= (\a -> return $ n + a))

-- Run before Proxy
runB :: (a -> Effect Identity r) -> a -> r
runB f a = runIdentity $ runEffect $ f a

-- Run after Proxy
runA :: (Monad m) => (m r -> Identity a) -> Effect m r -> a
runA f a = runIdentity $ f (runEffect a)

liftBenchmarks :: Int -> [Benchmark]
liftBenchmarks vmax =
    let applyBench = map ($ vmax)
    in
    [
      bgroup "ReaderT" $
        let defT f = (\d -> f d 1)
        in applyBench
        [
          bench "runReaderP_B" . whnf (runB (runReaderP 1) . r_bench)
        , bench "runReaderP_A" . whnf (runA (defT R.runReaderT) . r_bench)
        ]
    , bgroup "StateT" $
        let defT f = (\s -> f s 0)
        in applyBench
        [
          bench "runStateP_B"  . nf (runB (runStateP 0) . s_bench)
        , bench "runStateP_A"  . nf (runA (defT S.runStateT) . s_bench)
        , bench "evalStateP_B" . whnf (runB (evalStateP 0) . s_bench)
        , bench "evalStateP_A" . whnf (runA (defT S.evalStateT) . s_bench)
        , bench "execStateP_B" . whnf (runB (execStateP 0) . s_bench)
        , bench "execStateP_A" . whnf (runA (defT S.execStateT) . s_bench)
        ]
    ]


================================================
FILE: benchmarks/PreludeBench.hs
================================================
{-# LANGUAGE RankNTypes #-}
module Main (main) where

import Criterion.Main
import Common (commonMain)
import Control.Monad.Identity (Identity, runIdentity)
import Pipes
import qualified Pipes.Prelude as P
import Prelude hiding (enumFromTo)

defaultMax :: Int
defaultMax = 10000

main :: IO ()
main = commonMain defaultMax preludeBenchmarks

enumFromTo :: (Int -> a) -> Int -> Int -> Producer a Identity ()
enumFromTo f n1 n2 = loop n1
    where
        loop n =
            if n <= n2
            then do
                yield $! f n
                loop $! n + 1
            else return ()
{-# INLINABLE enumFromTo #-}

drain :: Producer b Identity r -> r
drain p = runIdentity $ runEffect $ for p discard

msum :: (Monad m) => Producer Int m () -> m Int
msum = P.foldM (\a b -> return $ a + b) (return 0) return

scanMSum :: (Monad m) => Pipe Int Int m r
scanMSum = P.scanM (\x y -> return (x + y)) (return 0) return

-- Using runIdentity seems to reduce outlier counts.
preludeBenchmarks :: Int -> [Benchmark]
preludeBenchmarks vmax =
    let applyBench b = b benchEnum_p
        benchEnum_p  = enumFromTo id 1 vmax
    in
    [
      bgroup "Folds" $ map applyBench
        [
          bench "all"       . whnf (runIdentity . P.all (<= vmax))
        , bench "any"       . whnf (runIdentity . P.any (> vmax))
        , bench "find"      . whnf (runIdentity . P.find (== vmax))
        , bench "findIndex" . whnf (runIdentity . P.findIndex (== vmax))
        , bench "fold"      . whnf (runIdentity . P.fold (+) 0 id)
        , bench "foldM"     . whnf (runIdentity . msum)
        , bench "head"      . nf (runIdentity . P.head)
        , bench "index"     . nf (runIdentity . P.index (vmax-1))
        , bench "last"      . nf (runIdentity . P.last)
        , bench "length"    . whnf (runIdentity . P.length)
        , bench "null"      . whnf (runIdentity  . P.null)
        , bench "toList"    . nf P.toList
        ]
    , bgroup "Pipes" $ map applyBench
        [
          bench "chain"       . whnf (drain . (>-> P.chain (\_ -> return ())))
        , bench "drop"        . whnf (drain . (>-> P.drop vmax))
        , bench "dropWhile"   . whnf (drain . (>-> P.dropWhile (<= vmax)))
        , bench "filter"      . whnf (drain . (>-> P.filter even))
        , bench "findIndices" . whnf (drain . (>-> P.findIndices (<= vmax)))
        , bench "map"         . whnf (drain . (>-> P.map id))
        , bench "mapM"        . whnf (drain . (>-> P.mapM return))
        , bench "take"        . whnf (drain . (>-> P.take vmax))
        , bench "takeWhile"   . whnf (drain . (>-> P.takeWhile (<= vmax)))
        , bench "scan"        . whnf (drain . (>-> P.scan (+) 0 id))
        , bench "scanM"       . whnf (drain . (>-> scanMSum))
        ] ++ [
          bench "concat" $ whnf (drain . (>-> P.concat)) $ enumFromTo Just 1 vmax
        ]
    , bgroup "Zips" $ map applyBench
        [
          bench "zip"     . whnf (drain . P.zip benchEnum_p)
        , bench "zipWith" . whnf (drain . P.zipWith (+) benchEnum_p)
        ]
    , bgroup "enumFromTo.vs.each"
        [
          bench "enumFromTo" $ whnf (drain . enumFromTo id 1) vmax
        , bench "each"       $ whnf (drain . each) [1..vmax]
        ]
    ]


================================================
FILE: laws.md
================================================
# Kleisli Category

    Define:
    
    return
        :: (Monad m)
        =>  r -> Proxy a' a b' b m r
    return = Pure
    
    (>=>)
        :: (Monad m)
        => (r -> Proxy a' a b' b m s)
        -> (s -> Proxy a' a b' b m t)
        -> (r -> Proxy a' a b' b m t)
    (f >=> g) x = f x >>= g
    
    (>>=)
        :: (Monad m)
        =>       Proxy a' a b' b m s
        -> (s -> Proxy a' a b' b m t)
        ->       Proxy a' a b' b m t
    p >>= f = case p of
        Request a' fa  -> Request a' (\a  -> fa  a  >>= f)
        Respond b  fb' -> Respond b  (\b' -> fb' b' >>= f)
        M          m   -> M (m >>= \p' -> return (p' >>= f))
        Pure    r      -> f r
    
## Left Identity Law

    Goal: return >=> f = f
    
    return >=> f
    
    -- Definition of `(>=>)`
    = \x -> return x >>= f
    
    -- [Kleisli Category - Left Identity Law - Pointful]
    = \x -> f x
    
    -- Eta reduce
    = f
    
    -- Goal complete
    
### Pointful

    Goal: return r >>= f = f r
    
    return r >>= f
    
    -- Definition of `return`
    = Pure r >>= f
    
    -- Definition of `(>>=)`
    = f r
    
    -- Goal complete
    
## Right Identity Law

    Goal: f >=> return = f
    
    f >=> return
    
    -- Definition of `(>=>)`
    = \x -> f x >>= return
    
    -- [Kleisli Category - Right Identity Law - Pointful]
    = \x -> f x
    
    -- Eta reduce
    = f
    
    -- Goal complete
    
### Pointful

    Goal: p >>= return = p
    
    p >>= return
    
    -- Definition of `(>>=)`
    = case p of
        Request a' fa  -> Request a' (\a -> fa a >>= return)
        
                        -- Coinduction: Reuse the premise
                        = Request a' (\a -> fa a)
                        
                        -- Eta reduce
                        = Request a' fa
                        
        Respond b  fb' -> Respond b (\b' -> fb' b' >>= return)
        
                        -- Coinduction: Reuse the premise
                        = Respond b (\b' -> fb' b')
                        
                        -- Eta reduce
                        = Respond b fb'
                        
        M          m   -> M (m >>= \p' -> return (p' >>= return))
        
                        -- Coinduction: Reuse the premise
                        = M (m >>= \p' -> return p')
                        
                        -- Eta reduce
                        = M (m >>= return)
                        
                        -- [Kleisli Category - Right Identity Law - Pointful] (NOTE: for base monad, so no coinduction necessary)
                        = M m
                        
        Pure    r      -> return r
        
                        -- Definition of `return`
                        = Pure r
                        
    -- Clean up
    = case p of
        Request a' fa  -> Request a' fa
        Respond b  fb' -> Respond b  fb'
        M          m   -> M          m
        Pure    r      -> Pure    r
        
    -- case statement = id
    = p
    
    -- Goal complete
    
## Associativity Law

    Goal: (f >=> g) >=> h = f >=> (g >=> h)
    
    (f >=> g) >=> h
    
    -- Definition of `(>=>)`
    = \x -> (f >=> g) x >>= h
    
    -- Definition of `(>=>)`
    = \x -> (f x >>= g) >>= h
    
    -- [Kleisli Category - Associativity Law - Pointful]
    = \x -> f x >>= \y -> g y >>= h
    
    -- Definition of `(>=>)`, in reverse
    = \x -> f x >>= (g >=> h)
    
    -- Definition of `(>=>)`, in reverse
    = f >=> (g >=> h)
    
    -- Goal complete

### Pointful

    Goal: (p >>= f) >>= g) = p >>= \x -> f x >>= g
    
    (p >>= f) >>= g
    
    -- Definition of `(>>=)`
    (case p of
        Request a' fa  -> Request a' (\a  -> fa  a  >>= f)
        Respond b  fb' -> Respond b  (\b' -> fb' b' >>= f)
        M          m   -> M (m >>= \p' -> return (p' >>= f))
        Pure    r      -> f r ) >>= g
        
    -- Distribute over case statement
    = case p of
        Request a' fa  -> Request a' (\a -> fa a >>= f) >>= g
        
                        -- Definition of `(>>=)`
                        = Request a' (\a -> (fa a >>= f) >>= g)
                        
                        -- Coinduction: Reuse the premise
                        = Request a' (\a -> fa a >>= \x -> f x >>= g)
                        
                        -- Definition of `(>>=)`, in reverse
                        = Request a' fa >>= \x -> f x >>= g
                        
        Respond b  fb' -> Respond b (\b' -> fb' b' >>= f) >>= g
        
                        -- Definition of `(>>=)`
                        = Respond b (\b' -> (fb' b' >>= f) >>= g)
                        
                        -- Coinduction: Reuse the premise
                        = Respond b (\b' -> fb' b' >>= \x -> f x >>= g)
                        
                        -- Definition of `(>>=)`, in reverse
                        = Respond b fb' >>= \x -> f x >>= g
                        
        M          m   -> M (m >>= \p' -> return (p' >>= f)) >>= g
        
                        -- Definition of `(>>=)`
                        = M (m >>= \p' -> return ((p' >>= f) >>= g))
                        
                        -- Coinduction: Reuse the premise
                        = M (m >>= \p' -> return (p' >>= \x -> f x >>= g))
                        
                        -- Definition of `(>>=)`, in reverse
                        = M m >>= \x -> f x >>= g
                        
        Pure    r      -> f r >>= g

                        -- Definition of `(>>=)`, in reverse
                        = Pure r >>= \x -> f x >>= g
                        
    -- Clean up
    = case p of
        Request a' fa  -> Request a' fa  >>= \x -> f x >>= g
        Respond b  fb' -> Respond b  fb' >>= \x -> f x >>= g
        M          m   -> M          m   >>= \x -> f x >>= g
        Pure    r      -> Pure    r      >>= \x -> f x >>= g
        
    -- Factor from case statement
    = (case p of
        Request a' fa  -> Request a' fa
        Respond b  fb' -> Respond b  fb'
        M          m   -> M          m
        Pure    r      -> Pure    r ) >>= \x -> f x >>= g
        
    -- case statement = id
    = p >>= \x -> f x >>= g
    
    -- Goal complete

# Respond Category

    Define:
    
    respond
        :: (Monad m)
        =>  a -> Proxy x' x a' a m a'
    respond a = Respond a Pure
    
    (/>/)
        :: (Monad m)
        => (a -> Proxy x' x b' b m a')
        -> (b -> Proxy x' x c' c m b')
        -> (a -> Proxy x' x c' c m a')
    (fa />/ fb) a = fa a //> fb
    
    (//>)
        :: (Monad m)
        =>       Proxy x' x b' b m a'
        -> (b -> Proxy x' x c' c m b')
        ->       Proxy x' x c' c m a'
    p //> fb = case p of
        Request x' fx  -> Request x' (\x -> fx x //> fb)
        Respond b  fb' -> fb b >>= \b' -> fb' b' //> fb
        M          m   -> M (m >>= \p' -> return (p' //> fb)
        Pure    a      -> Pure a

## Right Identity Law

    Goal: respond />/ fb = fb
    
    respond />/ fb
    
    -- Definition of `(/>/)`
    = \b -> respond b //> fb
    
    -- [Respond Category - Left Identity Law - Pointful]
    = \b -> fb b
    
    -- Eta reduce
    = fb
    
    -- Goal complete

### Pointful

    Goal: respond b //> fb = fb b
    
    -- Definition of `respond`
    = Respond b Pure //> fb
    
    -- Definition of `(//>)`
    = fb b >>= \b' -> Pure b' //> fb
    
    -- Definition of `(//>)`
    = fb b >>= \b' -> Pure b'
    
    -- Eta reduce
    = fb b >>= Pure
    
    -- Definition of `return` (in reverse)
    = fb b >>= return
    
    -- [Kleisli Category - Right Identity Law - Pointful]
    = fb b
    
    -- Goal complete

## Left Identity Law

    Goal: fa />/ respond = fa
        
    fa />/ respond
    
    -- Definition of '(/>/)'
    = \a -> fa a //> respond
    
    -- [Respond Category - Left Identity Law - Pointful]
    = \a -> fa a
    
    -- Eta reduce
    = fa
    
    -- Goal complete

### Pointful
    
    Goal: "Pointful": p //> respond = p
    
    p //> respond
    -- Definition of `(//>)`
    = case p of
        Request x' fx  -> Request x' (\x -> fx x //> respond)
        
                        -- Coinduction: Reuse the premise
                        = Request x' (\x -> fx x)
                        
                        -- Eta reduce
                        = Request x' fx
                        
        Respond b  fb' -> respond b >>= \b' -> fb' b' //> respond
        
                        -- Coinduction: Reuse the premise
                        = respond b >>= \b' -> fb' b'
                        
                        -- Eta reduce
                        = respond b >>= fb'
                        
                        -- Definition of `respond`
                        = Respond b Pure >>= fb'
                        
                        -- Definition of `(>>=)`
                        = Respond b (\b' -> Pure b' >>= fb')
                        
                        -- Definition of `return`, backwards
                        = Respond b (\b' -> return b' >>= fb')
                        
                        -- [Kleisli Category - Left Identity Law - Pointful]
                        = Respond b (\b' -> fb' b')
                        
                        -- Eta reduce
                        = Respond b fb'
                        
        M          m   -> M (m >>= \p' -> return (p' //> respond))
        
                        -- Coinduction: Reuse the premise
                        = M (m >>= \p' -> return p')
                        
                        -- Eta reduce
                        = M (m >>= return)
                        
                        -- [Kleisli Category - Right Identity Law - Pointful]
                        = M m
                        
        Pure    a'      -> Pure a'
    
    -- Clean up
    = case p of
        Request x' fx  -> Request x' fx
        Respond b  fb' -> Respond b  fb'
        M          m   -> M           m
        Pure    a'     -> Pure    a'
        
    -- case statement = id
    = p
    
    -- Goal complete

## Associativity Law

    Goal: (fa />/ fb) />/ fc = fa />/ (fb />/ fc)

    (fa />/ fb) />/ fc
    
    -- Definition of `(/>/)`
    \a -> ((fa />/ fb) a) //> fc
    
    -- Definition of `(/>/)`
    \a -> (fa a //> fb) //> fc
    
    -- [Respond Category - Associativity Law - Pointful]
    \a -> fa a //> \b -> fb b //> fc
    
    -- Definition of `(/>/)`, in reverse
    \a -> fa a //> (fb />/ fc)
    
    -- Definition of `(/>/)`, in reverse
    fa />/ (fb />/ fc)
    
    -- Goal complete
    
### Pointful

    Goal: (p //> fb) //> fc = p //> \b -> fb b //> fc
    
    (p //> fb) //> fc
    
    -- Definition of `(//>)`
    = (case p of
        Request x' fx  -> Request x' (\x -> fx x //> fb)
        Respond b  fb' -> fb b >>= \b' -> fb' b' //> fb
        M          m   -> M (m >>= \p' -> return (p' //> fb))
        Pure    a'     -> Pure a' ) //> fc
        
    -- Distribute over case statement
    = case p of
        Request x' fx  -> Request x' (\x -> fx x //> fb) //> fc
        
                        -- Definition of `(//>)`
                        = Request x' (\x -> (fx x //> fb) //> fc)
                        
                        -- Coinduction: Reuse the premise
                        = Request x' (\x -> fx x //> \b -> fb b //> fc)
                        
                        -- Definition of `(//>)`, in reverse
                        = Request x' fx //> \b -> fb //> fc
                        
        Respond b  fb' -> (fb b >>= \b' -> fb' b' //> fb) //> fc
        
                        -- [Respond Category - Distributivity Law - Pointful]
                        = (fb b //> fc) >>= \b' -> (fb' b' //> fb) //> fc
                        
                        -- Coinduction: Reuse the premise
                        = (fb b //> fc) >>= \b' -> fb' b' //> \b -> fb b //> fc
                        
                        -- [Kleisli Category - Right Identity Law - Pointful], in reverse
                        = ((fb b //> fc) >>= return) >>= \b' -> fb' b' //> \b -> fb b //> fc
                        
                        -- Definition of `return`
                        = ((fb b //> fc) >>= Pure) >>= \b' -> fb' b' //> \b -> fb b //> fc
                        
                        -- Eta expand
                        = ((fb b //> fc) >>= \r -> Pure r) >>= \b' -> fb' b' //> \b -> fb b //> fc
                        
                        -- Definition of `(//>)` in reverse
                        = ((fb b //> fc) >>= \r -> Pure r //> \b -> fb b //> fc) >>= \b' -> fb' b' //> \b -> fb b //> fc
                        
                        -- Definition of `(//>)` in reverse
                        = (Respond b Pure //> \b -> fb b //> fc) >>= \b' -> fb' b' //> \b -> fb b //> fc
                        
                        -- [Respond Category - Distributivity Law - Pointful], in reverse
                        = (Respond b Pure >>= \b' -> fb' b') //> \b -> fb b //> fc
                        
                        -- Eta reduce
                        = (Respond b Pure >>= fb') //> \b -> fb b //> fc
                        
                        -- Definition of `(>>=)`
                        = Respond b (\b' -> Pure b' >>= fb') //> \b -> fb b //> fc
                        
                        -- Definition of `(>>=)`
                        = Respond b (\b' -> fb' b') //> \b -> fb b //> fc
                        
                        -- Eta reduce
                        = Respond b fb' //> \b -> fb b //> fc
                        
        M          m   -> M (m >>= \p' -> return (p' //> fb)) //> fc
        
                        -- Definition of `(//>)`
                        = M (m >>= \p' -> return ((p' //> fb) //> fc))
                        
                        -- Coinduction: Reuse the premise
                        = M (m >>= \p' -> return (p' //> \b -> fb b //> fc))
                        
                        -- Definition of `(//>)`, in reverse
                        = M m //> \b -> fb b //> fc
                        
        Pure    a'      = Pure a' //> fc
        
                        -- Definition of `(//>)`
                        = Pure a'
                        
                        -- Definition of `(//>)`, in reverse
                        = Pure a' //> \b -> fb b //> fc
                        
    -- Clean up
    = case p of
        Request x' fx  -> Request x' fx  //> \b -> fb b //> fc
        Respond b  fb' -> Respond b  fb' //> \b -> fb b //> fc
        M          m   -> M          m   //> \b -> fb b //> fc
        Pure       a'  -> Pure    a'     //> \b -> fb b //> fc
        
    -- Factor from case statement
    = (case p of
        Request x' fx  -> Request x' fx
        Respond b  fb' -> Respond b  fb'
        M          m   -> M          m
        Pure       a'  -> Pure    a' ) //> \b -> fb b //> fc
        
    -- case statement = id
    = p //> \b -> fb b //> fc
    
    -- Goal complete

## Distributivity Law

    Goal: (k1 >=> k2) />/ fb = (k1 />/ fb) >=> (k2 />/ fb)
    
    (k1 >=> k2) />/ fb
    
    -- Definition of `(/>/)`
    = \a -> ((k1 >=> k2) a) //> fb
    
    -- Definition of `(>=>)`
    = \a -> (k1 a >>= k2) //> fb
    
    -- [Respond Category - Distributivity Law - Pointful]
    = \a -> (k1 a //> fb) >>= \r -> k2 r //> fb
    
    -- Definition of `(/>/)`, in reverse
    = \a -> (k1 />/ fb) a >>= \r -> k2 r //> fb
    
    -- Definition of `(/>/)`, in reverse
    = \a -> (k1 />/ fb) a >>= (k2 />/ fb)
    
    -- Definition of `(>=>)`, in reverse
    = (k1 />/ fb) >=> (k2 />/ fb)
    
    -- Goal complete
    
### Pointful

    Goal: (p >>= k) //> fb = (p //> fb) >>= \r -> k r //> fb
    
    (p >>= k) //> fb
    
    -- Definition of `(>>=)`
    = (case p of
        Request x' fx  -> Request x' (\x  -> fx  x  >>= k)
        Respond b  fb' -> Respond b  (\b' -> fb' b' >>= k)
        M          m   -> M (m >>= \p' -> return (p' >>= k))
        Pure    r      -> k r ) //> fb
        
    -- Distribute over case statement
    = case p of
        Request x' fx  -> Request x' (\x -> fx x >>= k) //> fb
        
                        -- Definition of `(//>)`
                        = Request x' (\x -> (fx x >>= k) //> fb)
                        
                        -- Coinduction: Reuse the premise
                        = Request x' (\x -> (fx x //> fb) >>= \r -> k r //> fb)
                        
                        -- Definition of `(>>=)`, in reverse
                        = Request x' (\x -> (fx x //> fb)) >>= \r -> k r //> fb
                        
                        -- Definition of `(//>)`, in reverse
                        = (Request x' fx //> fb) >>= \r -> k r //> fb
                        
        Respond b  fb' -> Respond b (\b' -> fb' b' >>= k) //> fb
        
                        -- Definition of `(//>)`
                        = fb b (\b' -> (fb' b' >>= k) //> fb)
                        
                        -- Coinduction: Reuse the premise
                        = fb b >>= \b' -> (fb' b' //> fb) >>= \r -> k r //> fb
                        
                        -- [Kleisli Category - Associativity Law - Pointful]
                        = (fb b >>= \b' -> fb' b' //> fb) >>= \r -> k r //> fb
                        
                        -- Definition of `(//>)`, in reverse
                        = (Respond b fb' //> fb) >>= \r -> k r //> fb
                        
        M          m   -> M (m >>= \p' -> return (p >>= k)) //> fb
        
                        -- Definition of `(//>)`
                        = M (m >>= \p' -> return ((p >>= k) //> fb))
                        
                        -- Coinduction: Reuse the premise
                        = M (m >>= \p' -> return ((p //> fb) >>= \r -> k r //> fb))
                        
                        -- Definition of `(>>=)`, in reverse
                        = M (m >>= \p' -> return (p //> fb)) >>= \r -> k r //> fb
                        
                        -- Definition of `(//>)`, in reverse
                        = (M m //> fb) >>= \r -> k r //> fb
                        
        Pure    r      -> k r //> fb
        
                        -- Definition of `(>>=)`, in reverse
                        = Pure r >>= \r -> k r //> fb
                        
                        -- Definition of `(//>)`, in reverse
                        = (Pure r //> fb) >>= \r -> k r //> fb
                        
    -- Clean up
    = case p of
        Request x' fx  -> (Request x' fx  //> fb) >>= \r -> k r //> fb
        Respond b  fb' -> (Respond b  fb' //> fb) >>= \r -> k r //> fb
        M          m   -> (M          m   //> fb) >>= \r -> k r //> fb
        Pure    r      -> (Pure    r      //> fb) >>= \r -> k r //> fb
        
    -- Factor from case statement
    = ((case p of
        Request x' fx  -> Request x' fx
        Respond b  fb' -> Respond b  fb'
        M          m   -> M          m
        Pure    r      -> Pure    r ) //> fb) >>= \r -> k r //> fb
        
    -- case statement = id
    = (p //> fb) >>= \r -> k r //> fb
    
    -- Goal complete

## Zero Law

    Goal: return />/ f = return
    
    return />/ f
    
    -- Definition of `(/>/)`
    = \r -> return r //> f
    
    -- [Respond Category - Zero Law - Pointful]
    = \r -> return r
    
    -- Eta reduce
    = return
    
    -- Goal complete
    
### Pointful

    Goal: return r //> f = return r
    
    return r //> f
    
    -- Definition of `return`
    = Pure r //> f
    
    -- Definition of `(//>)`
    = Pure r
    
    -- Definition of `return`, in reverse
    = return r
    
    -- Goal complete

# Request Category

    Define:
    
    request
        :: (Monad m)
        =>  a' -> Proxy a' a y' y m a
    request a' = Request a' Pure
    
    (\>\)
        :: (Monad m)
        => (b' -> Proxy a' a y' y m b)
        -> (c' -> Proxy b' b y' y m c)
        -> (c' -> Proxy a' a y' y m c)
    (fb' \>\ fc') c' = fb' >\\ fc' c'
    
    (>\\)
        :: (Monad m)
        => (b' -> Proxy a' a y' y m b)
        ->        Proxy b' b y' y m c
        ->        Proxy a' a y' y m c
    fb' >\\ p = case p of
        Request b' fb  -> fb' b' >>= \b -> fb' >\\ fb b
        Respond y  fy' -> Respond y (\y' -> fb' >\\ fy' y')
        M          m   -> M (m >>= \p' -> return (fb' >\\ p'))
        Pure       c   -> Pure c

## Left Identity Law

    Goal: request \>\ fc' = fc'

    request \>\ fc' = fc'
    
    -- Definition of `(\>\)`
    = \c' -> request >\\ fc' c'
    
    -- [Request Category - Left Identity Law - Pointful]
    = \c' -> fc' c'
    
    -- Eta reduce
    = fc'
    
    -- Goal complete
    
### Pointful

    Goal: request >\\ p = p
    
    -- Definition of `(>\\)`
    case p of
        Request b' fb  -> request b' >>= \b -> request >\\ fb b
        
                        -- Coinduction: Reuse the premise
                        = request b' >>= \b -> fb b
                        
                        -- Eta reduce
                        = request b' >>= fb
                        
                        -- Definition of `request`
                        = Request b' Pure >>= fb
                        
                        -- Definition of `(>>=)`
                        = Request b' (\b -> Pure b >>= fb)
                        
                        -- Definition of `(>>=)`
                        = Request b' (\b -> fb b)
                        
                        -- Eta reduce
                        = Request b' fb
                        
        Respond y  fy' -> Respond y (\y' -> request >\\ fy' y')
        
                        -- Coinduction: Reuse the premise
                        = Respond y (\y' -> fy' y')
                        
                        -- Eta reduce
                        = Respond y fy'
                        
        M          m   -> M (m >>= \p' -> return (request >\\ p'))
        
                        -- Coinduction: Reuse the premise
                        = M (m >>= \p' -> return p')
                        
                        -- Eta reduce
                        = M (m >>= return)
                        
                        -- [Kleisli Category - Right Identity Law - Pointful]
                        = M m
                        
        Pure    c       = Pure c
    
    -- Clean up
    = case p of
        Request b' fb  -> Request b' fb
        Respond y  fy' -> Respond y  fy'
        M          m   -> M          m
        Pure    c      -> Pure    c
    
    -- case statement = if
    = p
    
    -- Goal complete

## Right Identity Law

    Goal: fb' \>\ request = fb'
    
    fb' \>\ request
    
    -- Definition of `(\>\)`
    = \b' -> fb' >\\ request b'
    
    -- [Request Category - Right Identity Law - Pointful]
    = \b' -> fb' b'
    
    -- Eta reduce
    = fb'
    
    -- Goal complete

### Pointful

    Goal: fb' >\\ request b' = fb' b'
    
    fb' >\\ request b'
    
    -- Definition of `request`
    = fb' >\\ Request b' Pure
    
    -- Definitoin of `(>\\)`
    = fb' b' >>= \b -> fb' >\\ Pure b
    
    -- Definition of `(>\\)`
    = fb' b' >>= \b -> Pure b
    
    -- Eta reduce
    = fb' b' >>= Pure
    
    -- Definition of `return`, in reverse
    = fb' b' >>= return
    
    -- [Kleisli Category - Right Identity Law - Pointful]
    = fb' b'
    
    -- Goal complete

## Associativity Law

    Goal: (f \>\ g) \>\ h = f \>\ (g \>\ h)
    
    (f \>\ g) \>\ h
    
    -- Definition of `(\>\)`
    = \x -> (f \>\ g) >\\ h x
    
    -- Definition of `(\>\)`
    = \x -> (\y -> f >\\ g y) >\\ h x
    
    -- [Request Category - Composition - Pointful]
    = \x -> f >\\ (g >\\ h x)
    
    -- Definition of `(\>\)`, in reverse
    = \x -> f >\\ (g \>\ h) x
    
    -- Definition of `(\>\)`, in reverse
    = f \>\ (g \>\ h)
    
    -- Goal complete
    
### Pointful

    Goal: fa' >\\ (fb' >\\ p) = (\b' -> fa' >\\ fb' b') >\\ p
    
    fa' >\\ (fb' >\\ p)
    
    -- Definition of `(>\\)`
    = fa' >\\ (case p of
        Request b' fb  -> fb' b' >>= \b -> fb' >\\ fb b
        Respond y  fy' -> Respond y (\y' -> fb' >\\ fy' y')
        M          m   -> M (m >>= \p' -> return (fb' >\\ p'))
        Pure    c      -> Pure c
        
    -- Distribute over case statement
    = case p of
        Request b' fb  -> fa' >\\ (fb' b' >>= \b -> fb' >\\ fb b)
        
                        -- [Request Category - Distributivity Law]
                        = (fa' >\\ fb' b') >>= \b -> fa' >\\ (fb' >\\ fb b)
                        
                        -- Coinduction : Reuse the premise
                        = (fa' >\\ fb' b') >>= \b -> (\b' -> fa' >\\ fb' b') >\\ fb b
                        
                        -- [Kleisli Category - Right Identity Law - Pointful], in reverse
                        = ((fa' >\\ fb' b') >>= return) >>= \b -> (\b' -> fa' >\\ fb' b') >\\ fb b
                        
                        -- Definition of `return`
                        = ((fa' >\\ fb' b') >>= Pure) >>= \b -> (\b' -> fa' >\\ fb' b') >\\ fb b
                        
                        -- Eta expand
                        = ((fa' >\\ fb' b') >>= \r -> Pure r) >>= \b -> (\b' -> fa' >\\ fb' b') >\\ fb b
                        
                        -- Definition of `(>\\)`, in reverse
                        = ((fa' >\\ fb' b') >>= \r -> (\b' -> fa' >\\ fb' b') >\\ Pure r) >>= \b -> (\b' -> fa' >\\ fb' b') >\\ fb b
                        
                        -- Definition of `(>\\)`, in reverse
                        = ((\b' -> fa' >\\ fb' b') >\\ Request b' Pure) >>= \b -> (\b' -> fa' >\\ fb' b') >\\ fb b
                        
                        -- [Request Category - Distributivity Law - Pointful], in reverse
                        = (\b' -> fa' >\\ fb' b') >\\ (Request b' Pure >>= fb)
                        
                        -- Definition of `(>>=)`
                        = (\b' -> fa' >\\ fb' b') >\\ Request b' (\b -> Pure b >>= fb)
                        
                        -- Definition of `(>>=)`
                        = (\b' -> fa' >\\ fb' b') >\\ Request b' (\b -> fb b)
                        
                        -- Eta reduce
                        = (\b' -> fa' >\\ fb' b') >\\ Request b' fb
                        
        Respond y  fy' -> fa' >\\ Respond y (\y' -> fb' >\\ fy' y')
        
                        -- Definition of `(>\\)`
                        = Respond y (\y' -> fa' >\\ (fb' >\\ fy' y'))
                        
                        -- Coinduction: Reuse the premise
                        = Respond y (\y' -> (\b' -> fa' >\\ fb' b') >\\ fy' y')
                        
                        -- Definition of `(>\\)`, in reverse
                        = (\b' -> fa' >\\ fb' b') >\\ Respond y fy'
                        
        M          m   -> fa' >\\ M (m >>= \p' -> return (fb' >\\ p'))
        
                        -- Definition of `(>\\)`
                        = M (m >>= \p' -> return (fa' >\\ (fb' >\\ p')))
                        
                        -- Coinduction: Reuse the premise
                        = M (m >>= \p' -> return ((\b' -> fa' >\\ fb' b') >\\ p'))
                        
                        -- Definition of `(>\\)`, in reverse
                        = (\b' -> fa' >\\ fb' b') >\\ M m
                        
        Pure    c       = fa' >\\ Pure c
        
                        -- Definition of `(>\\)`
                        = Pure c
                        
                        -- Definition of `(>\\)`, in reverse
                        = (\b' -> fa' >\\ fb' b') >\\ Pure c
    
    -- Clean up
    = case p of
        Request b' fb  -> (\b' -> fa' >\\ fb' b') >\\ Request b' fb
        Request y  fy' -> (\b' -> fa' >\\ fb' b') >\\ Respond y  fy'
        M          m   -> (\b' -> fa' >\\ fb' b') >\\ M          m
        Pure    c      -> (\b' -> fa' >\\ fb' b') >\\ Pure    c
    
    -- Factor from case statement
    = (\b' -> fa' >\\ fb' b') >\\ (case p of
        Request b' fb  -> Request b' fb
        Respond y  fy' -> Respond y  fy'
        M          m   -> M          m
        Pure    c      -> Pure    c )
    
    -- case statement = id
    = (\b' -> fa' >\\ fb' b') >\\ p
    
    -- Goal complete
    
## Distributivity Law

    Goal: fb' \>\ (k1 >=> k2) = (fb' \>\ k1) >=> (fb' \>\ k2)
    
    fb' \>\ (k1 >=> k2)
    
    -- Definition of `(\>\)`
    = \x -> fb' >\\ ((k1 >=> k2) x)
    
    -- Definition of `(>=>)`
    = \x -> fb' >\\ (k1 x >>= k2)
    
    -- [Request Category - Distributivity Law - Pointful]
    = \x -> (fb' >\\ k1 x) >>= \y -> fb' >\\ k2 y
    
    -- Definition of `(\>\)`, in reverse
    = \x -> (fb' >\\ k1 x) >>= (fb' \>\ k2)
    
    -- Definition of `(\>\)`, in reverse
    = \x -> (fb' \>\ k1) x >>= (fb' \>\ k2)
    
    -- Definition of `(>=>)`, in reverse
    = (fb' \>\ k1) >=> (fb' \>\ k2)
    
    -- Goal complete

### Pointful

    Goal: fb' >\\ (p >>= k) = (fb' >\\ p) >>= \r -> fb' >\\ k r
    
    fb' >\\ (p >>= k)
    
    -- Definition of `(>>=)`
    = fb' >\\ (case p of
        Request b' fb  -> Request b' (\b  -> fb  b  >>= k)
        Respond y  fy' -> Respond y  (\y' -> fy' y' >>= k)
        M          m   -> M (m >>= \p' -> return (p' >>= k))
        Pure    c      -> k c )
    
    -- Distribute over case statement
    = case p of
        Request b' fb  -> fb' >\\ Request b' (\b -> fb b >>= k)
        
                        -- Definition of `(>\\)`
                        = fb' b' >>= \b -> fb' >\\ (fb b >>= k)
                        
                        -- Coinduction: Reuse the premise
                        = fb' b' >>= \b -> (fb' >\\ fb b) >>= \r -> fb' >\\ k r
                        
                        -- [Kleisli Category -- Associativity Law - Pointful]
                        = (fb' b' >>= \b -> fb' >\\ fb b) >>= \r -> fb' >\\ k r
                        
                        -- Definition of `(>\\)`, in reverse
                        = (fb' >\\ Request b' fb) >>= \r -> fb' >\\ k r
        
        Respond y  fy' -> fb' >\\ Respond y (\y' -> fy' y' >>= k)
                        
                        -- Definition of `(>\\)`
                        = Respond y (\y' -> fb' >\\ (fy' y' >>= k))
                        
                        -- Coinduction: Reuse the premise
                        = Respond y (\y' -> (fb' >\\ fy' y') >>= \r -> fb' >\\ k r)
                        
                        -- Definition of `(>>=)`, in reverse
                        = Respond y (\y' -> (fb' >\\ fy' y')) >>= \r -> fb' >\\ k r
                        
                        -- Definition of `(>\\)`, in reverse
                        = (fb' >\\ Respond y fy') >>= \r -> fb' >\\ k r
                        
        M          m   -> fb' >\\ M (m >>= \p' -> return (p' >>= k))
                        
                        -- Definition of `(>\\)`
                        = M (m >>= \p' -> return (fb' >\\ (p' >>= k)))
                        
                        -- Coinduction: Reuse the premise
                        = M (m >>= \p' -> return ((fb' >\\ p') >>= \r -> fb' >\\ k r))
                        
                        -- Definition of `(>>=)`, in reverse
                        = M (m >>= \p' -> return (fb' >\\ p')) >>= \r -> fb' >\\ k r
                        
                        -- Definition of `(>\\)`, in reverse
                        = (fb' >\\ M m) >>= \r -> fb' >\\ k r
                        
        Pure    c       = fb' >\\ k c
        
                        -- [Kleisli Category - Left Identity Law - Pointful], in reverse
                        = return c >>= \r -> fb' >\\ k r
                        
                        -- Definition of `return`
                        = Pure c >>= \r -> fb' >\\ k r
                        
                        -- Definition of `(>\\)`, in reverse
                        = (fb' >\\ Pure c) >>= \r -> fb' >\\ k r

    -- Clean up
    = case p of
        Request b' fb  -> (fb' >\\ Request b' fb ) >>= \r -> fb' >\\ k r
        Respond y  fy' -> (fb' >\\ Respond y  fy') >>= \r -> fb' >\\ k r
        M          m   -> (fb' >\\ M          m  ) >>= \r -> fb' >\\ k r
        Pure    c      -> (fb' >\\ Pure    c     ) >>= \r -> fb' >\\ k r
    
    -- Factor from case statement
    = (fb' >\\ case p of
        Request b' fb  -> Request b' fb
        Respond y  fy' -> Respond y  fy'
        M          m   -> M          m
        Pure    c      -> Pure    c ) >>= \r -> fb' >\\ k r
    
    -- case statement = id
    = (fb' >\\ p) >>= \r -> fb' >\\ k r
    
    -- Goal complete

## Zero Law

    Goal: f \>\ return = return
    
    f \>\ return
    
    -- Definition of `(\>\)`
    = \r -> f >\\ return r
    
    -- [Request Category - Zero Law - Pointful]
    = \r -> return r
    
    -- Eta reduce
    = return
    
    -- Goal complete
    
### Pointful

    Goal: f >\\ return r = return r
    
    f >\\ return r
    
    -- Definition of `return`
    = f >\\ Pure r
    
    -- Definition of `(>\\)`
    = Pure r
    
    -- Definition of `return`, in reverse
    = return r
    
    -- Goal complete

# Pull Category

    Define:
    
    pull
        :: (Monad m)
        =>   a' -> Proxy a' a a' a m r
    pull a' = Request a' push
    
    (>+>)
        :: (Monad m)
        => ( b' -> Proxy a' a b' b m r)
        -> (_c' -> Proxy b' b c' c m r)
        -> (_c' -> Proxy a' a c' c m r)
    (fb' >+> fc') c' = fb' +>> fc' c'
    
    (+>>)
        :: (Monad m)
        => ( b' -> Proxy a' a b' b m r)
        ->         Proxy b' b c' c m r
        ->         Proxy a' a c' c m r
    fb' +>> p = case p of
        Request b' fb  -> fb' b' >>~ fb
        Respond c  fc' -> Respond c (\c' -> fb' +>> fc' c')
        M          m   -> M (m >>= \p' -> return (fb' +>> p'))
        Pure       r   -> Pure r
        
## Left Identity Law

    Goal: pull >+> f = f
    
    pull >+> f
    
    -- Definition of `(>+>)`
    = \c' -> pull +>> f c'
    
    -- [Pull Category - Left Identity Law - Pointful]
    = \c' -> f c'
    
    -- Eta reduce
    = f
    
    -- Goal complete
    
### Pointful

    Goal: pull +>> p = p
    
    pull +>> p
    
    -- Definition of `(+>>)`
    = case p of
        Request b' fb  -> pull b' >>~ fb
                        
                        -- Definition of `pull`
                        = Request b' (\b -> Respond b pull) >>~ fb
                        
                        -- Definition of `(>>~)`
                        = Request b' (\b -> Respond b pull >>~ fb)
                        
                        -- Definition of `(>>~)`
                        = Request b' (\b -> pull +>> fb b)
                        
                        -- Coinduction: Reuse the premise
                        = Request b' (\b -> fb b)
                        
                        -- Eta reduce
                        = Request b' fb
                        
        Respond c  fc' -> Respond c (\c' -> pull +>> fc' c')
        
                        -- Coinduction: Reuse the premise
                        = Respond c (\c' -> fc' c')
                        
                        -- Eta reduce
                        = Respond c fc'
                        
        M          m   -> M (m >>= \p' -> return (pull +>> p'))
        
                        -- Coinduction: Reuse the premise
                        = M (m >>= \p' -> return p')
                        
                        -- Eta reduce
                        = M (m >>= return)
                        
                        -- [Kleisli Category - Right Identity Law - Pointful]
                        = M m
                        
        Pure    r      -> Pure r
    
    -- Clean up
    = case p of
        Request b' fb  -> Request b' fb
        Respond c  fc' -> Respond c  fc'
        M          m   -> M          m
        Pure    r      -> Pure r
    
    -- case statement = id
    = p
    
    -- Goal complete
    
## Right Identity Law

    Goal: fb' >+> pull = fb'
    
    fb' >+> pull
    
    -- Definition of `(>+>)`
    = \b' -> fb' +>> pull b'
    
    -- [Pull Category - Right Identity Law - Pointful]
    = \b' -> fb' b'
    
    -- Eta reduce
    = fb'
    
    -- Goal complete
    
### Pointful

    Goal: fb' +>> pull b' = fb' b'
    
    fb' +>> pull b'
    
    -- Definition of `push`
    = fb' +>> Request b' (\b -> Respond b pull)
    
    -- Definition of `(+>>)`
    = fb' b' >>~ \b -> Respond b pull
    
    -- Definition of `push`, in reverse
    = fb' b' >>~ push
    
    -- Coinduction: [Push Category - Right Identity Law - Pointful]
    = fb' b'
    
    -- Goal complete

## Associativity Law

    Goal: fb' >+> (fc' >+> fd') = (fb' >+> fc') >+> fd'
    
    fb' >+> (fc' >+> fd')
    
    -- Definition of `(>+>)`
    = \d' -> fb' +>> (fc' >+> fd') d'
    
    -- Definition of `(>+>)`
    = \d' -> fb' +>> (fc' +>> fd' d')
    
    -- [Pull Category - Associativity Law - Pointful]
    = \d' -> (\c' -> fb' +>> fc' c') +>> fd' d'
    
    -- Definition of `(>+>)`, in reverse
    = \d' -> (fb' >+> fc') +>> fd' d'
    
    -- Definition of `(>+>)`, in reverse
    = (fb' >+> fc') >+> fd'
    
    -- Goal complete
    
### Pointful

    Goal: fb' +>> (fc' +>> p) = (\c' -> fb' +>> fc' c') +>> p
    
    fb' +>> (fc' +>> p)
    
    -- Definition of `(+>>)`
    = fb' +>> (case p of
        Request c' fc  -> fc' c' >>~ fc
        Respond d  fd' -> Respond d (\d' -> fc' +>> fd' d')
        M          m   -> M (m >>= \p' -> return (fc' +>> p'))
        Pure    r      -> Pure r )
        
    -- Distribute over case statement
    = case p of
        Request c' fc  -> fb' +>> (fc' c' >>~ fc)
        
                        -- Coinduction: [Push/Pull - Associativity - Pointful]
                        = (fb' +>> fc' c') >>~ fc
                       
                        -- Definition of `(+>>), in reverse
                        = (\c' -> fb' +>> fc' c') +>> Request c' fc
                       
        Respond d  fd' -> fb' +>> Respond d (\d' -> fc' +>> fd' d')
        
                        -- Definition of `(+>>)`
                        = Respond d (\d' -> fb' +>> (fc' +>> fd' d'))
                        
                        -- Coinduction: Reuse the premise
                        = Respond d (\d' -> (\c' -> fb' +>> fc' c') +>> fd' d')
                        
                        -- Definition of `(+>>)`, in reverse
                        = (\c' -> fb' +>> fc' c') +>> Respond d fd'
        
        M          m   -> fb' +>> M (m >>= \p' -> return (fc' +>> p'))
        
                        -- Definition of `(+>>)`
                        = M (m >>= \p' -> return (fb' +>> (fc' +>> p')))
                        
                        -- Coinduction: Reuse the premise
                        = M (m >>= \p' -> return ((\c' -> fb' +>> fc' c') +>> p'))
                        
                        -- Definition of `(+>>)`, in reverse
                        = (\c' -> fb' +>> fc' c') +>> M m
                        
        Pure    r      -> fb' +>> Pure r
        
                       -- Definition of `(+>>)`
                       = Pure r
                       
                       -- Definition of `(+>>)`, in reverse
                       = (\c' -> fb' +>> fc' c') +>> Pure r
                       
    -- Clean up
    = case p of
        Request c' fc  -> (\c' -> fb' +>> fc' c') +>> Request c' fc
        Respond d  fd' -> (\c' -> fb' +>> fc' c') +>> Respond d  fd'
        M          m   -> (\c' -> fb' +>> fc' c') +>> M          m
        Pure       r   -> (\c' -> fb' +>> fc' c') +>> Pure    r
    
    -- Factor from case statement
    = (\c' -> fb' +>> fc' c') +>> (case p of
        Request c' fc  -> Request c' fc
        Respond d  fd' -> Respond d  fd'
        M          m   -> M          m
        Pure    r      -> Pure    r )
    
    -- case statement = id
    = (\c' -> fb' +>> fc' c') +>> p
    
    -- Goal complete

# Push Category

    Define:

    push
        :: (Monad m)
        =>   a -> Proxy a' a a' a m r
    push a = Respond a pull

    (>~>)
        :: (Monad m)
        => (_a -> Proxy a' a b' b m r)
        -> ( b -> Proxy b' b c' c m r)
        -> (_a -> Proxy a' a c' c m r)
    (f >~> g) x = f x >>~ g

    (>>~)
        :: (Monad m)
        =>        Proxy a' a b' b m r
        -> ( b -> Proxy b' b c' c m r)
        ->        Proxy a' a c' c m r
    p >>~ fb = case p of
        Request a' fa  -> Request a' (\a -> fa a >>~ fb)
        Respond b  fb' -> fb' +>> fb b
        M          m   -> M (m >>= \p' -> return (p' >>~ fb))
        Pure    r      -> Pure r

## Left Identity Law

    Goal: push >~> f = f
    
    push >~> f
    
    -- Definition of `(>~>)`
    = \a -> push a >>~ f
    
    -- [Push Category - Left Identity Law - Pointful]
    = \a -> f a
    
    -- Eta reduce
    = f
    
    -- Goal complete
    
### Pointful

    Goal: push a >>~ f = f a
    
    push a >>~ f
    
    -- Definition of `push`
    = Respond a pull >>~ f
    
    -- Definition of `(>>~)`
    = pull +>> f a
    
    -- Coinduction: [Pull Category - Left Identity Law - Pointful]
    = f a
    
    -- Goal complete

## Right Identity Law

    Goal: f >~> push = f
    
    f >~> push
    
    -- Definition of `(>~>)`
    = \a -> f a >>~ push
    
    -- [Push Category - Right Identity Law - Pointful]
    = \a -> f a
    
    -- Eta reduce
    = f
    
    -- Goal complete
    
### Pointful

    Goal: p >>~ push = p
    
    p >>~ push
    
    -- Definition of `(>>~)`
    = case p of
        Request a' fa  -> Request a' (\a -> fa a >>~ push)
         
                        -- Coinduction: Reuse the premise
                        = Request a' (\a -> fa a)
                        
                        -- Eta reduce
                        = Request a' fa
                       
        Respond b  fb' -> fb' +>> push b
        
                        -- Definition of `push`
                        = fb' +>> Respond b pull
                        
                        -- Definition of `(+>>)`
                        = Respond b (fb' +>> pull)
                        
                        -- [Pull Category - Right Identity Law - Pointful]
                        = Respond b fb'
                        
        M          m   -> M (m >>= \p' -> return (p >>~ push))
        
                        -- Coinduction: Reuse the premise
                        = M (m >>= \p' -> return p)
                        
                        -- Eta reduce
                        = M (m >>= return)
                        
                        -- [Kleisli Category - Right Identity Law - Pointful]
                        = M m
                        
        Pure    r      -> Pure r
    
    -- Clean up
    = case p of
        Request a' fa  -> Request a' fa
        Respond b  fb' -> Respond b  fb'
        M          m   -> M          m
        Pure    r      -> Pure    r
    
    -- case statement = id
    = p
    
    -- Goal complete
    
## Associativity Law

    Goal: (fa >~> fb) >~> fc = fa >~> (fb >~> fc)
    
    (fa >~> fb) >~> fc
    
    -- Definition of `(>~>)`
    = \a -> (fa >~> fb) a >>~ fc
    
    -- Definition of `(>~>)`
    = \a -> (fa a >>~ fb) >>~ fc
    
    -- [Push Category - Associativity Law - Pointful]
    = \a -> fa a >>~ \b -> fb b >>~ fc
    
    -- Definition of `(>~>)`, in reverse
    = \a -> fa a >>~ (fb >~> fc)
    
    -- Definition of `(>~>)`, in reverse
    = fa >~> (fb >~> fc)`
    
    -- Goal complete
    
### Pointful

    Goal: (p >>~ fb) >>~ fc = p >>~ \b -> fb b >>~ fc
    
    (p >>~ fb) >>~ fc
    
    -- Definition of `(>>~)`
    = (case p of
        Request a' fa  -> Request a' (\a -> fa a >>~ fb)
        Respond b  fb' -> fb' +>> fb b
        M          m   -> M (m >>= \p' -> return (p' >>~ fb))
        Pure    r      -> Pure r ) >>~ fc
        
    -- Distribute over case statement
    = case p of
        Request a' fa  -> Request a' (\a -> fa a >>~ fb) >>~ fc
        
                        -- Definition of `(>>~)`
                        = Request a' (\a -> (fa a >>~ fb) >>~ fc)
                        
                        -- Coinduction: Reuse the premise
                        = Request a' (\a -> fa a >>~ \b -> fb b >>~ fc)
                        
                        -- Definition of `(>>~), in reverse
                        = Request a' fa >>~ \b -> fb b >>~ fc
                       
        Respond b  fb' -> (fb' +>> fb b) >>~ fc
        
                        -- Coinduction: [Push/Pull - Associativity - Pointful]
                        = fb' +>> (fb b >>~ fc)
                        
                        -- Definition of `(>>~)`, in reverse
                        = Respond b fb' >>~ \b -> fb b >>~ fc
                        
        M          m   -> M (m >>= \p' -> return (p' >>~ fb)) >>~ fc
        
                        -- Definition of `(>>~)`
                        = M (m >>= \p' -> return ((p >>~ fb) >>~ fc))
                        
                        -- Coinduction: Reuse the premise
                        = M (m >>= \p' -> return (p >>~ \b -> fb b >>~ fc))
                        
                        -- Definition of `(>>~), in reverse
                        = M m >>~ \b -> fb b >>~ fc
                        
        Pure    r      -> Pure r >>~ fc
        
                        -- Definition of `(>>~)`
                        = Pure r
                        
                        -- Definition of `(>>~)`, in reverse
                        = Pure r >>~ \b -> fb b >>~ fc
                        
    -- Clean up
    = case p of
        Request a' fa  -> Request a' fa  >>~ \b -> fb b >>~ fc
        Respond b  fb' -> Respond b  fb' >>~ \b -> fb b >>~ fc
        M          m   -> M          m   >>~ \b -> fb b >>~ fc
        Pure    r      -> Pure    r      >>~ \b -> fb b >>~ fc
        
    -- Factor from case statement
    = (case p of
        Request a' fa  -> Request a' fa
        Respond b  fb' -> Respond b  fb'
        M          m   -> M          m
        Pure    r      -> Pure    r ) >>~ \b -> fb b >>~ fc
        
    -- case statement = id
    = p >>~ \b -> fb b >>~ fc
    
    -- Goal complete
        
# Push/Pull

## Associativity

    Goal: (f >+> g) >~> h = f >+> (g >~> h)
    
    (f >+> g) >~> h
    
    -- Definition of `(>~>)`
    = \x -> (f >+> g) x >>~ h
    
    -- Definition of `(>+>)`
    = \x -> (f +>> g x) >>~ h
    
    -- [Push/Pull - Associativity - Pointful]
    = \x -> f +>> (g x >>~ h)
    
    -- Definition of `(>~>)`, in reverse
    = \x -> f +>> (g >~> h)x
    
    -- Definition of `(>+>)`, in reverse
    = f >+> (g >~> h)
    
    -- Goal complete

### Pointful

    Goal: (fb' +>> p) >>~ fc = fb' +>> (p >>~ fc)
    
    (fb' +>> p) >>~ fc
    
    -- Definition of `(+>>)`
    = (case p of
        Request b' fb  -> fb' b' >>~ fb
        Respond c  fc' -> Respond c (\c' -> fb' +>> fc' c')
        M          m   -> M (m >>= \p' -> return (fb' +>> p'))
        Pure    r      -> Pure r ) >>~ fc
        
    -- Distribute over case statement
    = case p of
        Request b' fb  -> (fb' b' >>~ fb) >>~ fc
        
                        -- Coinduction: [Push Category - Associativity Law - Pointful]
                        = fb' b' >>~ \b -> fb b >>~ fc
                        
                        -- Definition of `(+>>)`, in reverse
                        = fb' +>> Request b' (\b -> fb b >>~ fc)
                       
                        -- Definition of `(>>~)`, in reverse
                        = fb' +>> (Request b' fb >>~ fc)
                       
        Respond c  fc' -> Respond c (\c' -> fb' +>> fc' c') >>~ fc
        
                        -- Definition of `(>>~)`
                        = (\c' -> fb' +>> fc' c') +>> fc c
                        
                        -- Coinduction: [Pull Category - Associativity Law - Pointful]
                        = fb' +>> (fc' +>> fc c)
                        
                        -- Definition of `(>>~)`, in reverse
                        = fb' +>> (Respond c fc' >>~ fc)
                        
        M          m   -> M (m >>= \p' -> return (fb' +>> p')) >>~ fc
        
                        -- Definition of `(>>~)`
                        = M (m >>= \p' -> return ((fb' +>> p') >>~ fc))
                        
                        -- Coinduction: Reuse the premise
                        = M (m >>= \p' -> return (fb' +>> (p' >>~ fc))
                        
                        -- Definition of `(+>>)`, in reverse
                        = fb' +>> M (m >>= \p' -> return (p' >>~ fc))
                        
                        -- Definition of `(>>~)`, in reverse
                        = fb' +>> (M m >>~ fc)
                        
        Pure    r      -> Pure r >>~ fc
         
                        -- Definition of `(+>>)`, in reverse
                        = fb' +>> (Pure r >>~ fc)
                        
    -- Clean up
    = case p of
        Request b' fb  -> fb' +>> (Request b' fb  >>~ fc)
        Respond c  fc' -> fb' +>> (Respond c  fc' >>~ fc)
        M          m   -> fb' +>> (M          m   >>~ fc)
        Pure    r      -> fb' +>> (Pure    r      >>~ fc)
        
    -- Factor from case statement
    = fb' +>> ((case p of
        Request b' fb  -> Request b' fb
        Respond c  fc' -> Respond c  fc'
        M          m   -> M          m
        Pure    r      -> Pure    r ) >>~ fc)
        
    -- case statement = id
    = fb' +>> (p >>~ fc)
    
    -- Goal complete
    
# Duals

    Define:
    
    reflect
        :: (Monad m)
        => Proxy a' a b' b m r
        -> Proxy b b' a a' m r
    reflect p = case p of
        Request a' fa  -> Respond a' (\a  -> go (fa  a ))
        Respond b  fb' -> Request b  (\b' -> go (fb' b'))
        M          m   -> M (m >>= \p' -> return (go p'))
        Pure    r      -> Pure r

## Request Identity

    Goal: reflect . request = respond
    
    reflect . request
    
    -- Definition of `(.)`
    = \a' -> reflect (request a')
    
    -- [Dual - Request Identity - Pointful]
    = \a' -> respond a'
    
    -- Eta reduce
    = respond
    
    -- Goal complete

### Pointful

    Goal: reflect (request x) = respond x
    
    reflect (request x)
    
    -- Definition of `request`
    = reflect (Request x Pure)
    
    -- Definition of `reflect`
    = Respond x (\r -> reflect (Pure r))
    
    -- Definition of `reflect`
    = Respond x (\r -> Pure r)
    
    -- Eta reduce
    = Respond x Pure
    
    -- Definition of `respond`, in reverse
    = respond
    
    -- Goal complete

## Request Composition

    Goal: reflect . (f \>\ g) = reflect . g />/ reflect . f
    
    reflect . (f \>\ g)
    
    -- Definition of `(.)`
    = \a -> reflect ((f \>\ g) a)
    
    -- Definition of `(\>\)`
    = \a -> reflect (f >\\ g a)
    
    -- [Dual - Request Composition - Pointful]
    = \a -> reflect (g a) //> reflect . f
    
    -- Definition of `(.)`, in reverse
    = \a -> (reflect . g) a //> reflect . f
    
    -- Definition of `(/>/)`, in reverse
    = reflect . g />/ reflect . f
    
    -- Goal complete
    
### Pointful

    Goal: reflect (f >\\ p) = reflect p //> reflect . f
    
    reflect (f >\\ p)
    
    -- Definition of `(>\\)`
    = reflect (case p of
        Request b' fb  -> f b' >>= \b -> f >\\ f b
        Respond x  fx' -> Respond x (\x' -> f >\\ fx' x')
        M          m   -> M (m >>= \p' -> return (f >\\ p'))
        Pure       c   -> Pure c )
        
    -- Distribute over case statement
    = case p of
        Request b' fb  -> reflect (f b' >>= \b -> f >\\ fb b)
        
                        -- [Dual - Distributivity Law - Pointful]
                        = reflect (f b') >>= \b -> reflect (f >\\ fb b)
                        
                        -- Coinduction: Reuse the premise
                        = reflect (f b') >>= \b -> reflect (fb b) //> reflect . f
                        
                        -- Definition of `(.)`, in reverse
                        = (reflect . f) b' >>= \b -> reflect (fb b) //> reflect . f
                        
                        -- Definition of `(//>)`, in reverse
                        = Respond b' (\b -> reflect (fb b)) //> reflect . f
                        
                        -- Definition of `reflect`, in reverse
                        = reflect (Request b' fb) //> reflect . f
                        
        Respond x  fx' -> reflect (Respond x (\x' -> f >\\ fx' x'))
        
                        -- Definition of `reflect`
                        = Request x (\x' -> reflect (f >\\ fx' x'))
                        
                        -- Coinduction: Reuse the premise
                        = Request x (\x' -> reflect (fx' x') //> reflect . f)
                        
                        -- Definition of `(//>)`, in reverse
                        = Request x (\x' -> reflect (fx' x')) //> reflect . f
                        
                        -- Definition of `reflect`, in reverse
                        = reflect (Respond x fx') //> reflect . f
                        
        M          m   -> reflect (M (m >>= \p' -> return (f >\\ p')))
        
                        -- Definition of `reflect`
                        = M (m >>= \p' -> return (reflect (f >\\ p')))
                        
                        -- Coinduction: Reuse the premise
                        = M (m >>= \p' -> return (reflect p' //> reflect . f))
                        
                        -- Definition of `(//>)`, in reverse
                        = M (m >>= \p' -> return (reflect p')) //> reflect . f
                        
                        -- Definition of `reflect, in reverse
                        = reflect (M m) //> reflect . f
                        
        Pure    c       = reflect (Pure c)
        
                        -- Definition of `reflect
                        = Pure c
                        
                        -- Definition of `(//>)`, in reverse
                        = Pure c //> reflect . f
                        
                        -- Definition of `reflect`, in reverse
                        = reflect (Pure c) //> reflect .f
                        
    -- Clean up
    = case p of
        Request b' fb  -> reflect (Request b' fb ) //> reflect . f
        Respond x  fx' -> reflect (Respond x  fx') //> reflect . f
        M          m   -> reflect (M          m  ) //> reflect . f
        Pure       c   -> reflect (Pure    c     ) //> reflect . f
        
    -- Factor from case statement
    = reflect (case p of
        Request b' fb  -> Request b' fb
        Respond x  fx' -> Respond x  fx'
        M          m   -> M          m
        Pure       c   -> Pure     c ) //> reflect . f
        
    -- case statement = id
    = reflect p //> reflect . f
    
    -- Goal complete

## Respond Identity

    Goal: reflect . respond = request
    
    reflect . respond
    
    -- Definition of `(.)`
    = \a -> reflect (respond a)
    
    -- [Dual - Respond Identity - Pointful]
    = \a -> request a
    
    -- Eta reduce
    = request
    
    -- Goal complete
    
### Pointful

    Goal: reflect (respond x) = request x
    
    reflect (respond x)
    
    -- Definition of `respond`
    = reflect (Respond x Pure)
    
    -- Definition of `reflect`
    = Request x (\r -> reflect (Pure r))
    
    -- Definition of `reflect`
    = Request x (\r -> Pure r)
    
    -- Eta reduce
    = Request x Pure
    
    -- Definition of `request`, in reverse
    = request
     
    -- Goal complete

## Respond Composition

    Goal: reflect . (f />/ g) = reflect . g \>\ reflect . f
    
    reflect . (f />/ g)
    
    -- Definition of `(.)`
    = \x -> reflect ((f />/ g) x)
    
    -- Definition of `(/>/)`
    = \x -> reflect (f x //> g)
    
    -- [Dual - Respond Composition - Pointful]
    = \x -> reflect . g >\\ reflect (f x)
    
    -- Definition of `(.)`, in reverse
    = \x -> reflect . g >\\ (reflect . f) x
    
    -- Definition of `(\>\)`, in reverse
    = reflect . g \>\ reflect . f
    
    -- Goal complete

### Pointful

    Goal: reflect (p //> f) = reflect . f >\\ reflect p
    
    reflect (p //> f)
    
    -- Definition of `(//>)`
    = reflect (case p of
        Request x' fx  -> Request x' (\x -> fx x //> f)
        Respond b  fb' -> f b >>= \b' -> fb' b' //> f
        M          m   -> M (m >>= \p' -> return (p' //> f))
        Pure    a'     -> Pure a' )
        
    -- Distribute over case statement
    = case p of
        Request x' fx  -> reflect (Request x' (\x -> fx x //> f))
        
                         -- Definition of `reflect`
                         = Respond x' (\x -> reflect (fx x //> f))
                         
                         -- Coinduction: Reuse the premise
                         = Respond x' (\x -> reflect . f >\\ reflect (fx x))
                         
                         -- Definition of `(>\\)`, in reverse
                         = reflect . f >\\ Respond x' (\x -> reflect (fx x))
                         
                         -- Definition of `reflect`, in reverse
                         = reflect . f >\\ reflect (Request x' fx)
                         
        Respond b  fb' -> reflect (f b >>= \b' -> fb' b' //> f)
        
                        -- [Dual - Distributivity Law - Pointful]
                        = reflect (f b) >>= \b' -> reflect (fb' b' //> f)
                        
                        -- Coinduction: Reuse the premise
                        = reflect (f b) >>= \b' -> reflect . f >\\ reflect (fb' b')
                        
                        -- Definition of `(.)`
                        = (reflect . f) b >>= \b' -> reflect . f >\\ reflect (fb' b')
                        
                        -- Definition of `(>\\)`, in reverse
                        = reflect . f >\\ (Request b (\b' -> reflect (fb' b')))
                        
                        -- Definition of `reflect`, in reverse
                        = reflect . f >\\ reflect (Respond b fb')
                        
        M          m    = reflect (M (m >>= \p' -> return (p' //> f)))
        
                        -- Definition of `reflect`
                        = M (m >>= \p' -> return (reflect (p' //> f)))
                        
                        -- Coinduction: Reuse the premise
                        = M (m >>= \p' -> return (reflect . f >\\ reflect p'))
                        
                        -- Definition of `(>\\)`, in reverse
                        = reflect . f >\\ M (m >>= \p' -> return (reflect p'))
                        
                        -- Definition of `reflect`, in reverse
                        = reflect . f >\\ reflect (M m)
                        
        Pure    a'      = reflect (Pure a')
        
                        -- Definition of `reflect`
                        = Pure a'
                        
                        -- Definition of `(>\\)`, in reverse
                        = reflect . f >\\ Pure a'
                        
                        -- Definition of `reflect`, in reverse
                        = reflect . f >\\ reflect (Pure a')
                        
    -- Clean up
    = case p of
        Request x' fx  -> reflect . f >\\ reflect (Request x' fx )
        Respond b  fb' -> reflect . f >\\ reflect (Respond b  fb')
        M          m   -> reflect . f >\\ reflect (M          m  )
        Pure    a'     -> reflect . f >\\ reflect (Pure    a'    )
    
    -- Factor from case statement
    = reflect . f >\\ reflect (case p of
        Request x' fx  -> Request x' fx
        Respond b  fb' -> Respond b  fb'
        M          m   -> M          m
        Pure    a'     -> Pure    a' )
    
    -- case statement = id
    = reflect . f >\\ reflect p
    
    -- Goal complete
    
## Distributivity Law

    Goal: reflect . (f >=> g) = reflect . f >=> reflect . g
    
    reflect . (f >=> g)
    
    -- Definition of `(.)`
    = \x -> reflect ((f >=> g) x)
    
    -- Definition of `(>=>)`
    = \x -> reflect (f x >>= g)
    
    -- [Dual - Distributive Law - Pointful]
    = \x -> reflect (f x) >>= \y -> reflect (g y)
    
    -- Definition of `(.)`, in reverse
    = \x -> reflect (f x) >>= reflect . g
    
    -- Definition of `(.)`, in reverse
    = \x -> ((reflect . f) x >>= reflect . g)
    
    -- Definition of `(>=>)`, in reverse
    = reflect . f >=> reflect . g
    
    -- Goal complete
    
### Pointful

    Goal: reflect (p >>= f) = reflect p >>= \x -> reflect (f x)
    
    reflect (p >>= f)
    
    -- Definition of `(>>=)`
    = reflect (case p of
        Request a' fa  -> Request a' (\a  -> fa  a  >>= f)
        Respond b  fb' -> Respond b  (\b' -> fb' b' >>= f)
        M          m   -> M (m >>= \p' -> return (p' >>= f))
        Pure    r      -> f r )
        
    -- Distribute over case statement
    = case p of
        Request a' fa  -> reflect (Request a' (\a -> fa a >>= f))
        
                        -- Definition of `reflect`
                        = Respond a' (\a -> reflect (fa a >>= f))
                        
                        -- Coinduction: Reuse the premise
                        = Respond a' (\a -> reflect (fa a) >>= \x -> reflect (f x))
                        
                        -- Definition of `(>>=)`, in reverse
                        = Respond a' (\a -> reflect (fa a)) >>= \x -> reflect (f x)
                        
                        -- Definition of `reflect`, in revrse
                        = reflect (Request a' (\a -> fa a)) >>= \x -> reflect (f x)
                        
                        -- Eta reduce
                        = reflect (Request a' fa) >>= \x -> reflect (f x)
                        
        Respond b  fb' -> reflect (Respond b (\b' -> fb' b' >>= f))
        
                        -- Definition of `reflect`
                        = Request b (\b' -> reflect (fb' b' >>= f))
                        
                        -- Coinduction: Reuse the premise
                        = Request b (\b' -> reflect (fb' b') >>= \x -> reflect (f x))
                        
                        -- Definition of `(>>=)`, in reverse
                        = Request b (\b' -> reflect (fb' b')) >>= \x -> reflect (f x)
                        
                        -- Definition of `reflect`, in reverse
                        = reflect (Respond b (\b' -> fb' b')) >>= \x -> reflect (f x)
                        
                        -- Eta reduce
                        = reflect (Respond b fb') >>= \x -> reflect (f x)
                        
        M          m   -> reflect (M (m >>= \p' -> return (p' >>= f)))
        
                        -- Definition of `reflect`
                        = M (m >>= \p' -> return (reflect (p' >>= f)))
                        
                        -- Coinduction: Reuse the premise
                        = M (m >>= \p' -> return (reflect p' >>= \x -> reflect (f x)))
                        
                        -- Definition of `(>>=)`, in reverse
                        = M (m >>= \p' -> return (reflect p')) >>= \x -> reflect (f x)
                        
                        -- Definition of `reflect`, in reverse
                        = reflect (M m) >>= \x -> reflect (f x)
                        
        Pure    r      -> reflect (f r)
        
                        -- [Kleisli Category - Left Identity - Pointful]
                        reflect (return r >>= f)
                        
                        -- Coinduction: Reuse the premise
                        reflect (return r) >>= \x -> return (f x)
                        
                        -- Definition of `return`
                        reflect (Pure r) >>= \x -> return (f x)
                        
    -- Cleanup
    = case p of
        Request a' fa  -> reflect (Request a' fa ) >>= \x -> reflect (f x)
        Respond b  fb' -> reflect (Respond b  fb') >>= \x -> reflect (f x)
        M          m   -> reflect (M          m  ) >>= \x -> reflect (f x)
        Pure    r      -> reflect (Pure    r     ) >>= \x -> reflect (f x)
        
    -- Factor from case statement
    = reflect (case p of
        Request a' fa  -> Request a' fa
        Respond b  fb' -> Respond b  fb'
        M          m   -> M          m
        Pure    r      -> Pure    r ) >>= \x -> reflect (f x)
        
    -- case statement = id
    = reflect p >>= \x -> reflect (f x)
    
    -- Goal complete
    
## Zero Law

    Goal: reflect . return = return
    
    reflect . return
    
    -- Definition of `(.)`
    = \r -> reflect (return r)
    
    -- [Dual - Zero Law - Pointful]
    = \r -> return r
    
    -- Eta reduce
    = return
    
    -- Goal complete
    
### Pointful

    Goal: reflect (return r) = return r
    
    reflect (return r)
    
    -- Definition of `return`
    = reflect (Pure r)
    
    -- Definition of `reflect`
    = Pure r
    
    -- Definition of `return`, in reverse
    = return r
    
    -- Goal complete
    
## Involution

    Goal: reflect . reflect = id
    
    reflect . reflect
    
    -- Definition of `(.)`
    = \p -> reflect (reflect p)
    
    -- [Dual - Involution]
    = \p -> p
    
    -- Definition of `id`
    = id
    
    -- Goal complete
    
### Pointful

    reflect (reflect p) = p
    
    reflect (reflect p)
    
    -- Definition of `reflect`
    = reflect (case p of
        Request a' fa  -> Respond a' (\a  -> reflect (fa  a ))
        Respond b  fb' -> Request b  (\b' -> reflect (fb' b'))
        M          m   -> M (m >>= \p' -> return (reflect p'))
        Pure    r      -> Pure r )
    
    -- Distribute over case statement
    = case p of
        Request a' fa  -> reflect (Respond a' (\a -> reflect (fa a))
        
                        -- Definition of `reflect`
                        = Request a' (\a -> reflect (reflect (fa  a)))
                        
                        -- Coinduction: Reuse the premise
                        = Request a' (\a -> fa a)
                        
                        -- Eta reduction
                        = Request a' fa
                        
        Respond b  fb' -> reflect (Request b (\b' -> reflect (fb' b')))
         
                        -- Definition of `reflect`
                        = Request b (\b' -> reflect (reflect (fb' b')))
                         
                        -- Coinduction: Reuse the premise
                        = Request b (\b' -> fb' b')
                         
                        -- Eta reduction
                        = Request b fb'
                         
        M          m   -> reflect (M (m >>= \p' -> return (reflect p')))
        
                        -- Definition of `reflect`
                        = M (m >>= \p' -> return (reflect (reflect p')))
                        
                        -- Coinduction: Reuse the premise
                        = M (m >>= \p' -> return p')
                        
                        -- Eta reduce
                        = M (m >>= return)
                        
                        -- [Kleisli Category - Right Identity Law - Pointful]
                        = M m
                        
        Pure    r      -> reflect (Pure r)
        
                        -- Definition of `reflect`
                        = Pure r
                        
    -- Clean up
    = case p of
        Request a' fa  -> Request a' fa
        Respond b  fb' -> Respond b  fb'
        M          m   -> M          m
        Pure       r   -> Pure r
    
    -- case statement = id
    = p
    
    -- Goal complete

================================================
FILE: nix/.gitkeep
================================================


================================================
FILE: pipes.cabal
================================================
Name: pipes
Version: 4.3.16
Cabal-Version: >= 1.10
Build-Type: Simple
Tested-With: GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.5, GHC == 8.8.1
License: BSD3
License-File: LICENSE
Copyright: 2012-2016 Gabriella Gonzalez
Author: Gabriella Gonzalez
Maintainer: GenuineGabriella@gmail.com
Bug-Reports: https://github.com/Gabriella439/Haskell-Pipes-Library/issues
Synopsis: Compositional pipelines
Description:
  `pipes` is a clean and powerful stream processing library that lets you build
  and connect reusable streaming components
  .
  Advantages over traditional streaming libraries:
  .
  * /Concise API/: Use simple commands like 'for', ('>->'), 'await', and 'yield'
  .
  * /Blazing fast/: Implementation tuned for speed, including shortcut fusion
  .
  * /Lightweight Dependency/: @pipes@ is small and compiles very rapidly,
    including dependencies
  .
  * /Elegant semantics/: Use practical category theory
  .
  * /ListT/: Correct implementation of 'ListT' that interconverts with pipes
  .
  * /Bidirectionality/: Implement duplex channels
  .
  * /Extensive Documentation/: Second to none!
  .
  Import "Pipes" to use the library.
  .
  Read "Pipes.Tutorial" for an extensive tutorial.
Category: Control, Pipes
Extra-Source-Files:
    CHANGELOG.md
Source-Repository head
    Type: git
    Location: https://github.com/Gabriella439/Haskell-Pipes-Library

Library
    Default-Language: Haskell2010

    HS-Source-Dirs: src
    Build-Depends:
        base         >= 4.8     && < 5   ,
        transformers >= 0.2.0.0 && < 0.7 ,
        exceptions   >= 0.4     && < 0.11,
        mmorph       >= 1.0.4   && < 1.3 ,
        mtl          >= 2.2.1   && < 2.4 ,
        void         >= 0.4     && < 0.8

    if impl(ghc < 8.0)
        Build-depends:
            fail       == 4.9.*         ,
            semigroups >= 0.17 && < 0.20

    Exposed-Modules:
        Pipes,
        Pipes.Core,
        Pipes.Internal,
        Pipes.Lift,
        Pipes.Prelude,
        Pipes.Tutorial
    GHC-Options: -O2 -Wall

Benchmark prelude-benchmarks
    Default-Language: Haskell2010
    Type:             exitcode-stdio-1.0
    HS-Source-Dirs:   benchmarks
    Main-Is:          PreludeBench.hs
    Other-Modules:    Common
    GHC-Options:     -O2 -Wall -rtsopts -fno-warn-unused-do-bind

    Build-Depends:
        base      >= 4.4     && < 5  ,
        criterion >= 1.1.1.0 && < 1.7,
        optparse-applicative >= 0.12 && < 0.18,
        mtl       >= 2.1     && < 2.4,
        pipes

test-suite tests
    Default-Language: Haskell2010
    Type:             exitcode-stdio-1.0
    HS-Source-Dirs:   tests
    Main-Is:          Main.hs
    GHC-Options:      -Wall -rtsopts -fno-warn-missing-signatures -fno-enable-rewrite-rules

    Build-Depends:
        base                       >= 4.4     && < 5   ,
        pipes                                          ,
        QuickCheck                 >= 2.4     && < 3   ,
        mtl                        >= 2.1     && < 2.4 ,
        test-framework             >= 0.4     && < 1   ,
        test-framework-quickcheck2 >= 0.2.0   && < 0.4 ,
        transformers               >= 0.2.0.0 && < 0.7

Benchmark lift-benchmarks
    Default-Language: Haskell2010
    Type:             exitcode-stdio-1.0
    HS-Source-Dirs:   benchmarks
    Main-Is:          LiftBench.hs
    Other-Modules:    Common
    GHC-Options:     -O2 -Wall -rtsopts -fno-warn-unused-do-bind

    Build-Depends:
        base                 >= 4.4     && < 5   ,
        criterion            >= 1.1.1.0 && < 1.7 ,
        optparse-applicative                     ,
        mtl                  >= 2.1     && < 2.4 ,
        pipes                                    ,
        transformers         >= 0.2.0.0 && < 0.7


================================================
FILE: release.nix
================================================
let
  overlay = pkgsNew: pkgsOld: {
    haskellPackages = pkgsOld.haskellPackages.override (old: {
      overrides =
        pkgsNew.lib.fold pkgsNew.lib.composeExtensions
          (old.overrides or (_: _: { }))
          [ (pkgsNew.haskell.lib.packageSourceOverrides {
              pipes = ./.;
            })
            (pkgsNew.haskell.lib.packagesFromDirectory {
              directory = ./nix;
            })
            (haskellPackagesNew: haskellPackagesOld: {
            })
          ];
    });
  };

  nixpkgs = builtins.fetchTarball {
    url = "https://github.com/NixOs/nixpkgs/archive/1b55bc5d4b5cb6b35d71e7fe22cae9558c312937.tar.gz";

    sha256 = "05761c8bi6chlj15428h3k30r8b8g4w3h0m4xpsj6f9qcz27d9nf";
  };

  pkgs = import nixpkgs { config = { }; overlays = [ overlay ]; };

in
  { pipes = pkgs.haskellPackages.pipes;
  }


================================================
FILE: shell.nix
================================================
(import ./release.nix).pipes.env


================================================
FILE: src/Pipes/Core.hs
================================================
{-| The core functionality for the 'Proxy' monad transformer

    Read "Pipes.Tutorial" if you want a beginners tutorial explaining how to use
    this library.  The documentation in this module targets more advanced users
    who want to understand the theory behind this library.

    This module is not exported by default, and I recommend you use the
    unidirectional operations exported by the "Pipes" module if you can.  You
    should only use this module if you require advanced features like:

    * bidirectional communication, or:

    * push-based 'Pipe's.
-}

{-# LANGUAGE RankNTypes, Trustworthy #-}

module Pipes.Core (
    -- * Proxy Monad Transformer
    -- $proxy
      Proxy
    , runEffect

    -- * Categories
    -- $categories

    -- ** Respond
    -- $respond
    , respond
    , (/>/)
    , (//>)

    -- ** Request
    -- $request
    , request
    , (\>\)
    , (>\\)

    -- ** Push
    -- $push
    , push
    , (>~>)
    , (>>~)

    -- ** Pull
    -- $pull
    , pull
    , (>+>)
    , (+>>)

    -- ** Reflect
    -- $reflect
    , reflect

    -- * Concrete Type Synonyms
    , X
    , Effect
    , Producer
    , Pipe
    , Consumer
    , Client
    , Server

    -- * Polymorphic Type Synonyms
    , Effect'
    , Producer'
    , Consumer'
    , Client'
    , Server'

    -- * Flipped operators
    , (\<\)
    , (/</)
    , (<~<)
    , (~<<)
    , (<+<)
    , (<\\)
    , (//<)
    , (<<+)

    -- * Re-exports
    , closed
    ) where

import Pipes.Internal (Proxy(..), X, closed)

{- $proxy
    Diagrammatically, you can think of a 'Proxy' as having the following shape:

@
 Upstream | Downstream
     +---------+
     |         |
 a' <==       <== b'
     |         |
 a  ==>       ==> b
     |    |    |
     +----|----+
          v
          r
@

    You can connect proxies together in five different ways:

    * ('Pipes.>+>'): connect pull-based streams

    * ('Pipes.>~>'): connect push-based streams

    * ('Pipes.\>\'): chain folds

    * ('Pipes./>/'): chain unfolds

    * ('Control.Monad.>=>'): sequence proxies

-}

-- | Run a self-contained 'Effect', converting it back to the base monad
runEffect :: Monad m => Effect m r -> m r
runEffect = go
  where
    go p = case p of
        Request v _ -> closed v
        Respond v _ -> closed v
        M       m   -> m >>= go
        Pure    r   -> return r
{-# INLINABLE runEffect #-}

{- * Keep proxy composition lower in precedence than function composition, which
     is 9 at the time of of this comment, so that users can write things like:


> lift . k >+> p
>
> hoist f . k >+> p

   * Keep the priorities different so that users can mix composition operators
     like:

> up \>\ p />/ dn
>
> up >~> p >+> dn

   * Keep 'request' and 'respond' composition lower in precedence than 'pull'
     and 'push' composition, so that users can do:

> read \>\ pull >+> writer

   * I arbitrarily choose a lower priority for downstream operators so that lazy
     pull-based computations need not evaluate upstream stages unless absolutely
     necessary.
-}
infixl 3 //>
infixr 3 <\\      -- GHC will raise a parse error if either of these lines ends
infixr 4 />/, >\\ -- with '\', which is why this comment is here
infixl 4 \<\, //<
infixl 5 \>\      -- Same thing here
infixr 5 /</
infixl 6 <<+
infixr 6 +>>
infixl 7 >+>, >>~
infixr 7 <+<, ~<<
infixl 8 <~<
infixr 8 >~>

{- $categories
    A 'Control.Category.Category' is a set of components that you can connect
    with a composition operator, ('Control.Category..'), that has an identity,
    'Control.Category.id'.  The ('Control.Category..') and 'Control.Category.id'
    must satisfy the following three 'Control.Category.Category' laws:

@
\-\- Left identity
'Control.Category.id' 'Control.Category..' f = f

\-\- Right identity
f 'Control.Category..' 'Control.Category.id' = f

\-\- Associativity
(f 'Control.Category..' g) 'Control.Category..' h = f 'Control.Category..' (g 'Control.Category..' h)
@

    The 'Proxy' type sits at the intersection of five separate categories, four
    of which are named after their identity:

@
                     Identity   | Composition |  Point-ful
                  +-------------+-------------+-------------+
 respond category |   'respond'   |     '/>/'     |     '//>'     |
 request category |   'request'   |     '\>\'     |     '>\\'     |
    push category |   'push'      |     '>~>'     |     '>>~'     |
    pull category |   'pull'      |     '>+>'     |     '+>>'     |
 Kleisli category |   'return'    |     'Control.Monad.>=>'     |     '>>='     |
                  +-------------+-------------+-------------+
@

    Each composition operator has a \"point-ful\" version, analogous to how
    ('>>=') is the point-ful version of ('Control.Monad.>=>').  For example,
    ('//>') is the point-ful version of ('/>/').  The convention is that the
    odd character out faces the argument that is a function.
-}

{- $respond
    The 'respond' category closely corresponds to the generator design pattern.

    The 'respond' category obeys the category laws, where 'respond' is the
    identity and ('/>/') is composition:

@
\-\- Left identity
'respond' '/>/' f = f

\-\- Right identity
f '/>/' 'respond' = f

\-\- Associativity
(f '/>/' g) '/>/' h = f '/>/' (g '/>/' h)
@

#respond-diagram#

    The following diagrams show the flow of information:

@
'respond' :: 'Functor' m
       =>  a -> 'Proxy' x' x a' a m a'

\          a
          |
     +----|----+
     |    |    |
 x' <==   \\ /==== a'
     |     X   |
 x  ==>   / \\===> a
     |    |    |
     +----|----+
          v
          a'

('/>/') :: 'Functor' m
      => (a -> 'Proxy' x' x b' b m a')
      -> (b -> 'Proxy' x' x c' c m b')
      -> (a -> 'Proxy' x' x c' c m a')

\          a                   /===> b                      a
          |                  /      |                      |
     +----|----+            /  +----|----+            +----|----+
     |    v    |           /   |    v    |            |    v    |
 x' <==       <== b' <==\\ / x'<==       <== c'    x' <==       <== c'
     |    f    |         X     |    g    |     =      | f '/>/' g |
 x  ==>       ==> b  ===/ \\ x ==>       ==> c     x  ==>       ==> c
     |    |    |           \\   |    |    |            |    |    |
     +----|----+            \\  +----|----+            +----|----+
          v                  \\      v                      v
          a'                  \\==== b'                     a'

('//>') :: 'Functor' m
      => 'Proxy' x' x b' b m a'
      -> (b -> 'Proxy' x' x c' c m b')
      -> 'Proxy' x' x c' c m a'

\                              /===> b
                             /      |
     +---------+            /  +----|----+            +---------+
     |         |           /   |    v    |            |         |
 x' <==       <== b' <==\\ / x'<==       <== c'    x' <==       <== c'
     |    f    |         X     |    g    |     =      | f '//>' g |
 x  ==>       ==> b  ===/ \\ x ==>       ==> c     x  ==>       ==> c'
     |    |    |           \\   |    |    |            |    |    |
     +----|----+            \\  +----|----+            +----|----+
          v                  \\      v                      v
          a'                  \\==== b'                     a'
@

-}

{-| Send a value of type @a@ downstream and block waiting for a reply of type
    @a'@

    'respond' is the identity of the respond category.
-}
respond :: Functor m => a -> Proxy x' x a' a m a'
respond a = Respond a Pure
{-# INLINABLE [1] respond #-}

{-| Compose two unfolds, creating a new unfold

@
(f '/>/' g) x = f x '//>' g
@

    ('/>/') is the composition operator of the respond category.
-}
(/>/)
    :: Functor m
    => (a -> Proxy x' x b' b m a')
    -- ^
    -> (b -> Proxy x' x c' c m b')
    -- ^
    -> (a -> Proxy x' x c' c m a')
    -- ^
(fa />/ fb) a = fa a //> fb
{-# INLINABLE (/>/) #-}

{-| @(p \/\/> f)@ replaces each 'respond' in @p@ with @f@.

    Point-ful version of ('/>/')
-}
(//>)
    :: Functor m
    =>       Proxy x' x b' b m a'
    -- ^
    -> (b -> Proxy x' x c' c m b')
    -- ^
    ->       Proxy x' x c' c m a'
    -- ^
p0 //> fb = go p0
  where
    go p = case p of
        Request x' fx  -> Request x' (\x -> go (fx x))
        Respond b  fb' -> fb b >>= \b' -> go (fb' b')
        M          m   -> M (go <$> m)
        Pure       a   -> Pure a
{-# INLINE [1] (//>) #-}

{-# RULES
    "(Request x' fx ) //> fb" forall x' fx  fb .
        (Request x' fx ) //> fb = Request x' (\x -> fx x //> fb);
    "(Respond b  fb') //> fb" forall b  fb' fb .
        (Respond b  fb') //> fb = fb b >>= \b' -> fb' b' //> fb;
    "(M          m  ) //> fb" forall    m   fb .
        (M          m  ) //> fb = M ((\p' -> p' //> fb) <$> m);
    "(Pure      a   ) //> fb" forall a      fb .
        (Pure    a     ) //> fb = Pure a;
  #-}

{- $request
    The 'request' category closely corresponds to the iteratee design pattern.

    The 'request' category obeys the category laws, where 'request' is the
    identity and ('\>\') is composition:

@
-- Left identity
'request' '\>\' f = f

\-\- Right identity
f '\>\' 'request' = f

\-\- Associativity
(f '\>\' g) '\>\' h = f '\>\' (g '\>\' h)
@

#request-diagram#

    The following diagrams show the flow of information:

@
'request' :: 'Functor' m
        =>  a' -> 'Proxy' a' a y' y m a

\          a'
          |
     +----|----+
     |    |    |
 a' <=====/   <== y'
     |         |
 a  ======\\   ==> y
     |    |    |
     +----|----+
          v
          a

('\>\') :: 'Functor' m
      => (b' -> 'Proxy' a' a y' y m b)
      -> (c' -> 'Proxy' b' b y' y m c)
      -> (c' -> 'Proxy' a' a y' y m c)

\          b'<=====\\                c'                     c'
          |        \\               |                      |
     +----|----+    \\         +----|----+            +----|----+
     |    v    |     \\        |    v    |            |    v    |
 a' <==       <== y'  \\== b' <==       <== y'    a' <==       <== y'
     |    f    |              |    g    |     =      | f '\>\' g |
 a  ==>       ==> y   /=> b  ==>       ==> y     a  ==>       ==> y
     |    |    |     /        |    |    |            |    |    |
     +----|----+    /         +----|----+            +----|----+
          v        /               v                      v
          b ======/                c                      c

('>\\') :: Functor m
      => (b' -> Proxy a' a y' y m b)
      -> Proxy b' b y' y m c
      -> Proxy a' a y' y m c

\          b'<=====\\
          |        \\
     +----|----+    \\         +---------+            +---------+
     |    v    |     \\        |         |            |         |
 a' <==       <== y'  \\== b' <==       <== y'    a' <==       <== y'
     |    f    |              |    g    |     =      | f '>\\' g |
 a  ==>       ==> y   /=> b  ==>       ==> y     a  ==>       ==> y
     |    |    |     /        |    |    |            |    |    |
     +----|----+    /         +----|----+            +----|----+
          v        /               v                      v
          b ======/                c                      c
@
-}

{-| Send a value of type @a'@ upstream and block waiting for a reply of type @a@

    'request' is the identity of the request category.
-}
request :: Functor m => a' -> Proxy a' a y' y m a
request a' = Request a' Pure
{-# INLINABLE [1] request #-}

{-| Compose two folds, creating a new fold

@
(f '\>\' g) x = f '>\\' g x
@

    ('\>\') is the composition operator of the request category.
-}
(\>\)
    :: Functor m
    => (b' -> Proxy a' a y' y m b)
    -- ^
    -> (c' -> Proxy b' b y' y m c)
    -- ^
    -> (c' -> Proxy a' a y' y m c)
    -- ^
(fb' \>\ fc') c' = fb' >\\ fc' c'
{-# INLINABLE (\>\) #-}

{-| @(f >\\\\ p)@ replaces each 'request' in @p@ with @f@.

    Point-ful version of ('\>\')
-}
(>\\)
    :: Functor m
    => (b' -> Proxy a' a y' y m b)
    -- ^
    ->        Proxy b' b y' y m c
    -- ^
    ->        Proxy a' a y' y m c
    -- ^
fb' >\\ p0 = go p0
  where
    go p = case p of
        Request b' fb  -> fb' b' >>= \b -> go (fb b)
        Respond x  fx' -> Respond x (\x' -> go (fx' x'))
        M          m   -> M (go <$> m)
        Pure       a   -> Pure a
{-# INLINE [1] (>\\) #-}

{-# RULES
    "fb' >\\ (Request b' fb )" forall fb' b' fb  .
        fb' >\\ (Request b' fb ) = fb' b' >>= \b -> fb' >\\ fb  b;
    "fb' >\\ (Respond x  fx')" forall fb' x  fx' .
        fb' >\\ (Respond x  fx') = Respond x (\x' -> fb' >\\ fx' x');
    "fb' >\\ (M          m  )" forall fb'    m   .
        fb' >\\ (M          m  ) = M ((\p' -> fb' >\\ p') <$> m);
    "fb' >\\ (Pure    a    )" forall fb' a      .
        fb' >\\ (Pure    a     ) = Pure a;
  #-}

{- $push
    The 'push' category closely corresponds to push-based Unix pipes.

    The 'push' category obeys the category laws, where 'push' is the identity
    and ('>~>') is composition:

@
\-\- Left identity
'push' '>~>' f = f

\-\- Right identity
f '>~>' 'push' = f

\-\- Associativity
(f '>~>' g) '>~>' h = f '>~>' (g '>~>' h)
@

    The following diagram shows the flow of information:

@
'push'  :: 'Functor' m
      =>  a -> 'Proxy' a' a a' a m r

\          a
          |
     +----|----+
     |    v    |
 a' <============ a'
     |         |
 a  ============> a
     |    |    |
     +----|----+
          v
          r

('>~>') :: 'Functor' m
      => (a -> 'Proxy' a' a b' b m r)
      -> (b -> 'Proxy' b' b c' c m r)
      -> (a -> 'Proxy' a' a c' c m r)

\          a                b                      a
          |                |                      |
     +----|----+      +----|----+            +----|----+
     |    v    |      |    v    |            |    v    |
 a' <==       <== b' <==       <== c'    a' <==       <== c'
     |    f    |      |    g    |     =      | f '>~>' g |
 a  ==>       ==> b  ==>       ==> c     a  ==>       ==> c
     |    |    |      |    |    |            |    |    |
     +----|----+      +----|----+            +----|----+
          v                v                      v
          r                r                      r
@

-}

{-| Forward responses followed by requests

@
'push' = 'respond' 'Control.Monad.>=>' 'request' 'Control.Monad.>=>' 'push'
@

    'push' is the identity of the push category.
-}
push :: Functor m => a -> Proxy a' a a' a m r
push = go
  where
    go a = Respond a (\a' -> Request a' go)
{-# INLINABLE [1] push #-}

{-| Compose two proxies blocked while 'request'ing data, creating a new proxy
    blocked while 'request'ing data

@
(f '>~>' g) x = f x '>>~' g
@

    ('>~>') is the composition operator of the push category.
-}
(>~>)
    :: Functor m
    => (_a -> Proxy a' a b' b m r)
    -- ^
    -> ( b -> Proxy b' b c' c m r)
    -- ^
    -> (_a -> Proxy a' a c' c m r)
    -- ^
(fa >~> fb) a = fa a >>~ fb
{-# INLINABLE (>~>) #-}

{-| @(p >>~ f)@ pairs each 'respond' in @p@ with a 'request' in @f@.

    Point-ful version of ('>~>')
-}
(>>~)
    :: Functor m
    =>       Proxy a' a b' b m r
    -- ^
    -> (b -> Proxy b' b c' c m r)
    -- ^
    ->       Proxy a' a c' c m r
    -- ^
p >>~ fb = case p of
    Request a' fa  -> Request a' (\a -> fa a >>~ fb)
    Respond b  fb' -> fb' +>> fb b
    M          m   -> M ((\p' -> p' >>~ fb) <$> m)
    Pure       r   -> Pure r
{-# INLINE [1] (>>~) #-}

{- $pull
    The 'pull' category closely corresponds to pull-based Unix pipes.

    The 'pull' category obeys the category laws, where 'pull' is the identity
    and ('>+>') is composition:

@
\-\- Left identity
'pull' '>+>' f = f

\-\- Right identity
f '>+>' 'pull' = f

\-\- Associativity
(f '>+>' g) '>+>' h = f '>+>' (g '>+>' h)
@

#pull-diagram#

    The following diagrams show the flow of information:

@
'pull'  :: 'Functor' m
      =>  a' -> 'Proxy' a' a a' a m r

\          a'
          |
     +----|----+
     |    v    |
 a' <============ a'
     |         |
 a  ============> a
     |    |    |
     +----|----+
          v
          r

('>+>') :: 'Functor' m
      -> (b' -> 'Proxy' a' a b' b m r)
      -> (c' -> 'Proxy' b' b c' c m r)
      -> (c' -> 'Proxy' a' a c' c m r)

\          b'               c'                     c'
          |                |                      |
     +----|----+      +----|----+            +----|----+
     |    v    |      |    v    |            |    v    |
 a' <==       <== b' <==       <== c'    a' <==       <== c'
     |    f    |      |    g    |     =      | f >+> g |
 a  ==>       ==> b  ==>       ==> c     a  ==>       ==> c
     |    |    |      |    |    |            |    |    |
     +----|----+      +----|----+            +----|----+
          v                v                      v
          r                r                      r
@

-}

{-| Forward requests followed by responses:

@
'pull' = 'request' 'Control.Monad.>=>' 'respond' 'Control.Monad.>=>' 'pull'
@

    'pull' is the identity of the pull category.
-}
pull :: Functor m => a' -> Proxy a' a a' a m r
pull = go
  where
    go a' = Request a' (\a -> Respond a go)
{-# INLINABLE [1] pull #-}

{-| Compose two proxies blocked in the middle of 'respond'ing, creating a new
    proxy blocked in the middle of 'respond'ing

@
(f '>+>' g) x = f '+>>' g x
@

    ('>+>') is the composition operator of the pull category.
-}
(>+>)
    :: Functor m
    => ( b' -> Proxy a' a b' b m r)
    -- ^
    -> (_c' -> Proxy b' b c' c m r)
    -- ^
    -> (_c' -> Proxy a' a c' c m r)
    -- ^
(fb' >+> fc') c' = fb' +>> fc' c'
{-# INLINABLE (>+>) #-}

{-| @(f +>> p)@ pairs each 'request' in @p@ with a 'respond' in @f@.

    Point-ful version of ('>+>')
-}
(+>>)
    :: Functor m
    => (b' -> Proxy a' a b' b m r)
    -- ^
    ->        Proxy b' b c' c m r
    -- ^
    ->        Proxy a' a c' c m r
    -- ^
fb' +>> p = case p of
    Request b' fb  -> fb' b' >>~ fb
    Respond c  fc' -> Respond c (\c' -> fb' +>> fc' c')
    M          m   -> M ((\p' -> fb' +>> p') <$> m)
    Pure       r   -> Pure r
{-# INLINABLE [1] (+>>) #-}

{- $reflect
    @(reflect .)@ transforms each streaming category into its dual:

    * The request category is the dual of the respond category

@
'reflect' '.' 'respond' = 'request'

'reflect' '.' (f '/>/' g) = 'reflect' '.' f '/</' 'reflect' '.' g
@

@
'reflect' '.' 'request' = 'respond'

'reflect' '.' (f '\>\' g) = 'reflect' '.' f '\<\' 'reflect' '.' g
@

    * The pull category is the dual of the push category

@
'reflect' '.' 'push' = 'pull'

'reflect' '.' (f '>~>' g) = 'reflect' '.' f '<+<' 'reflect' '.' g
@

@
'reflect' '.' 'pull' = 'push'

'reflect' '.' (f '>+>' g) = 'reflect' '.' f '<~<' 'reflect' '.' g
@
-}

-- | Switch the upstream and downstream ends
reflect :: Functor m => Proxy a' a b' b m r -> Proxy b b' a a' m r
reflect = go
  where
    go p = case p of
        Request a' fa  -> Respond a' (\a  -> go (fa  a ))
        Respond b  fb' -> Request b  (\b' -> go (fb' b'))
        M          m   -> M (go <$> m)
        Pure    r      -> Pure r
{-# INLINABLE reflect #-}

{-| An effect in the base monad

    'Effect's neither 'Pipes.await' nor 'Pipes.yield'
-}
type Effect = Proxy X () () X

-- | 'Producer's can only 'Pipes.yield'
type Producer b = Proxy X () () b

-- | 'Pipe's can both 'Pipes.await' and 'Pipes.yield'
type Pipe a b = Proxy () a () b

-- | 'Consumer's can only 'Pipes.await'
type Consumer a = Proxy () a () X

{-| @Client a' a@ sends requests of type @a'@ and receives responses of
    type @a@.

    'Client's only 'request' and never 'respond'.
-}
type Client a' a = Proxy a' a () X

{-| @Server b' b@ receives requests of type @b'@ and sends responses of type
    @b@.

    'Server's only 'respond' and never 'request'.
-}
type Server b' b = Proxy X () b' b

-- | Like 'Effect', but with a polymorphic type
type Effect' m r = forall x' x y' y . Proxy x' x y' y m r

-- | Like 'Producer', but with a polymorphic type
type Producer' b m r = forall x' x . Proxy x' x () b m r

-- | Like 'Consumer', but with a polymorphic type
type Consumer' a m r = forall y' y . Proxy () a y' y m r

-- | Like 'Server', but with a polymorphic type
type Server' b' b m r = forall x' x . Proxy x' x b' b m r

-- | Like 'Client', but with a polymorphic type
type Client' a' a m r = forall y' y . Proxy a' a y' y m r

-- | Equivalent to ('/>/') with the arguments flipped
(\<\)
    :: Functor m
    => (b -> Proxy x' x c' c m b')
    -- ^
    -> (a -> Proxy x' x b' b m a')
    -- ^
    -> (a -> Proxy x' x c' c m a')
    -- ^
p1 \<\ p2 = p2 />/ p1
{-# INLINABLE (\<\) #-}

-- | Equivalent to ('\>\') with the arguments flipped
(/</)
    :: Functor m
    => (c' -> Proxy b' b x' x m c)
    -- ^
    -> (b' -> Proxy a' a x' x m b)
    -- ^
    -> (c' -> Proxy a' a x' x m c)
    -- ^
p1 /</ p2 = p2 \>\ p1
{-# INLINABLE (/</) #-}

-- | Equivalent to ('>~>') with the arguments flipped
(<~<)
    :: Functor m
    => (b -> Proxy b' b c' c m r)
    -- ^
    -> (a -> Proxy a' a b' b m r)
    -- ^
    -> (a -> Proxy a' a c' c m r)
    -- ^
p1 <~< p2 = p2 >~> p1
{-# INLINABLE (<~<) #-}

-- | Equivalent to ('>+>') with the arguments flipped
(<+<)
    :: Functor m
    => (c' -> Proxy b' b c' c m r)
    -- ^
    -> (b' -> Proxy a' a b' b m r)
    -- ^
    -> (c' -> Proxy a' a c' c m r)
    -- ^
p1 <+< p2 = p2 >+> p1
{-# INLINABLE (<+<) #-}

-- | Equivalent to ('//>') with the arguments flipped
(<\\)
    :: Functor m
    => (b -> Proxy x' x c' c m b')
    -- ^
    ->       Proxy x' x b' b m a'
    -- ^
    ->       Proxy x' x c' c m a'
    -- ^
f <\\ p = p //> f
{-# INLINABLE (<\\) #-}

-- | Equivalent to ('>\\') with the arguments flipped
(//<)
    :: Functor m
    =>        Proxy b' b y' y m c
    -- ^
    -> (b' -> Proxy a' a y' y m b)
    -- ^
    ->        Proxy a' a y' y m c
    -- ^
p //< f = f >\\ p
{-# INLINABLE (//<) #-}

-- | Equivalent to ('>>~') with the arguments flipped
(~<<)
    :: Functor m
    => (b  -> Proxy b' b c' c m r)
    -- ^
    ->        Proxy a' a b' b m r
    -- ^
    ->        Proxy a' a c' c m r
    -- ^
k ~<< p = p >>~ k
{-# INLINABLE (~<<) #-}

-- | Equivalent to ('+>>') with the arguments flipped
(<<+)
    :: Functor m
    =>         Proxy b' b c' c m r
    -- ^
    -> (b'  -> Proxy a' a b' b m r)
    -- ^
    ->         Proxy a' a c' c m r
    -- ^
k <<+ p = p +>> k
{-# INLINABLE (<<+) #-}

{-# RULES
    "(p //> f) //> g" forall p f g . (p //> f) //> g = p //> (\x -> f x //> g)

  ; "p //> respond" forall p . p //> respond = p

  ; "respond x //> f" forall x f . respond x //>  f = f x

  ; "f >\\ (g >\\ p)" forall f g p . f >\\ (g >\\ p) = (\x -> f >\\ g x) >\\ p

  ; "request >\\ p" forall p . request >\\ p = p

  ; "f >\\ request x" forall f x . f >\\ request x = f x

  ; "(p >>~ f) >>~ g" forall p f g . (p >>~ f) >>~ g = p >>~ (\x -> f x >>~ g)

  ; "p >>~ push" forall p . p >>~ push = p

  ; "push x >>~ f" forall x f . push x >>~ f = f x

  ; "f +>> (g +>> p)" forall f g p . f +>> (g +>> p) = (\x -> f +>> g x) +>> p

  ; "pull +>> p" forall p . pull +>> p = p

  ; "f +>> pull x" forall f x . f +>> pull x = f x

  #-}


================================================
FILE: src/Pipes/Internal.hs
================================================
{-| This is an internal module, meaning that it is unsafe to import unless you
    understand the risks.

    This module provides a fast implementation by weakening the monad
    transformer laws.  These laws do not hold if you can pattern match on the
    constructors, as the following counter-example illustrates:

@
'lift' '.' 'return' = 'M' '.' 'return' '.' 'Pure'

'return' = 'Pure'

'lift' '.' 'return' /= 'return'
@

    You do not need to worry about this if you do not import this module, since
    the other modules in this library do not export the constructors or export
    any functions which can violate the monad transformer laws.
-}

{-# LANGUAGE CPP                   #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes            #-}
{-# LANGUAGE UndecidableInstances  #-}
{-# LANGUAGE Trustworthy           #-}

module Pipes.Internal (
    -- * Internal
      Proxy(..)
    , unsafeHoist
    , observe
    , X
    , closed
    ) where

import qualified Control.Monad.Fail as F (MonadFail(fail))
import Control.Monad.IO.Class (MonadIO(liftIO))
import Control.Monad.Trans.Class (MonadTrans(lift))
import Control.Monad.Morph (MFunctor(hoist), MMonad(embed))
import Control.Monad.Except (MonadError(..))
import Control.Monad.Catch (MonadThrow(..), MonadCatch(..))
import Control.Monad.Reader (MonadReader(..))
import Control.Monad.State (MonadState(..))
import Control.Monad.Writer (MonadWriter(..), censor)
import Data.Void (Void)

#if MIN_VERSION_base(4,8,0)
import Control.Applicative (Alternative(..))
#else
import Control.Applicative
#endif
import Data.Semigroup

import qualified Data.Void

{-| A 'Proxy' is a monad transformer that receives and sends information on both
    an upstream and downstream interface.

    The type variables signify:

    * @a'@ and @a@ - The upstream interface, where @(a')@s go out and @(a)@s
      come in

    * @b'@ and @b@ - The downstream interface, where @(b)@s go out and @(b')@s
      come in

    * @m @ - The base monad

    * @r @ - The return value
-}
data Proxy a' a b' b m r
    = Request a' (a  -> Proxy a' a b' b m r )
    | Respond b  (b' -> Proxy a' a b' b m r )
    | M          (m    (Proxy a' a b' b m r))
    | Pure    r

instance Functor m => Functor (Proxy a' a b' b m) where
    fmap f p0 = go p0 where
        go p = case p of
            Request a' fa  -> Request a' (\a  -> go (fa  a ))
            Respond b  fb' -> Respond b  (\b' -> go (fb' b'))
            M          m   -> M (go <$> m)
            Pure    r      -> Pure (f r)

instance Functor m => Applicative (Proxy a' a b' b m) where
    pure      = Pure
    pf <*> px = go pf where
        go p = case p of
            Request a' fa  -> Request a' (\a  -> go (fa  a ))
            Respond b  fb' -> Respond b  (\b' -> go (fb' b'))
            M          m   -> M (go <$> m)
            Pure    f      -> fmap f px
    l *> r = go l where
        go p = case p of
            Request a' fa  -> Request a' (\a  -> go (fa  a ))
            Respond b  fb' -> Respond b  (\b' -> go (fb' b'))
            M          m   -> M (go <$> m)
            Pure    _      -> r

instance Functor m => Monad (Proxy a' a b' b m) where
    return = pure
    (>>=)  = _bind

_bind
    :: Functor m
    => Proxy a' a b' b m r
    -> (r -> Proxy a' a b' b m r')
    -> Proxy a' a b' b m r'
p0 `_bind` f = go p0 where
    go p = case p of
        Request a' fa  -> Request a' (\a  -> go (fa  a ))
        Respond b  fb' -> Respond b  (\b' -> go (fb' b'))
        M          m   -> M (go <$> m)
        Pure    r      -> f r
{-# NOINLINE[1] _bind #-}

{-# RULES
    "_bind (Request a' k) f" forall a' k f .
        _bind (Request a' k) f = Request a' (\a  -> _bind (k a)  f);
    "_bind (Respond b  k) f" forall b  k f .
        _bind (Respond b  k) f = Respond b  (\b' -> _bind (k b') f);
    "_bind (M          m) f" forall m    f .
        _bind (M          m) f = M ((\p -> _bind p f) <$> m);
    "_bind (Pure    r   ) f" forall r    f .
        _bind (Pure    r   ) f = f r;
  #-}

instance (Functor m, Semigroup r) => Semigroup (Proxy a' a b' b m r) where
    p1 <> p2 = go p1 where
        go p = case p of
            Request a' fa  -> Request a' (\a  -> go (fa  a ))
            Respond b  fb' -> Respond b  (\b' -> go (fb' b'))
            M          m   -> M (go <$> m)
            Pure    r1     -> fmap (r1 <>) p2

instance (Functor m, Monoid r, Semigroup r) => Monoid (Proxy a' a b' b m r) where
    mempty        = Pure mempty
#if !(MIN_VERSION_base(4,11,0))
    mappend = (<>)
#endif

instance MonadTrans (Proxy a' a b' b) where
    lift m = M (Pure <$> m)

{-| 'unsafeHoist' is like 'hoist', but faster.

    This is labeled as unsafe because you will break the monad transformer laws
    if you do not pass a monad morphism as the first argument.  This function is
    safe if you pass a monad morphism as the first argument.
-}
unsafeHoist
    :: Functor m
    => (forall x . m x -> n x) -> Proxy a' a b' b m r -> Proxy a' a b' b n r
unsafeHoist nat = go
  where
    go p = case p of
        Request a' fa  -> Request a' (\a  -> go (fa  a ))
        Respond b  fb' -> Respond b  (\b' -> go (fb' b'))
        M          m   -> M (nat (go <$> m))
        Pure    r      -> Pure r
{-# INLINABLE unsafeHoist #-}

instance MFunctor (Proxy a' a b' b) where
    hoist nat p0 = go (observe p0)
      where
        go p = case p of
            Request a' fa  -> Request a' (\a  -> go (fa  a ))
            Respond b  fb' -> Respond b  (\b' -> go (fb' b'))
            M          m   -> M (nat (go <$> m))
            Pure    r      -> Pure r

instance MMonad (Proxy a' a b' b) where
    embed f = go
      where
        go p = case p of
            Request a' fa  -> Request a' (\a  -> go (fa  a ))
            Respond b  fb' -> Respond b  (\b' -> go (fb' b'))
            M          m   -> f m >>= go
            Pure    r      -> Pure r

instance F.MonadFail m => F.MonadFail (Proxy a' a b' b m) where
    fail = lift . F.fail

instance MonadIO m => MonadIO (Proxy a' a b' b m) where
    liftIO m = M (liftIO (Pure <$> m))

instance MonadReader r m => MonadReader r (Proxy a' a b' b m) where
    ask = lift ask
    local f = go
        where
          go p = case p of
              Request a' fa  -> Request a' (\a  -> go (fa  a ))
              Respond b  fb' -> Respond b  (\b' -> go (fb' b'))
              Pure    r      -> Pure r
              M       m      -> M (go <$> local f m)
    reader = lift . reader

instance MonadState s m => MonadState s (Proxy a' a b' b m) where
    get = lift get
    put = lift . put
    state = lift . state

instance MonadWriter w m => MonadWriter w (Proxy a' a b' b m) where
    writer = lift . writer
    tell = lift . tell
    listen p0 = go p0 mempty
      where
        go p w = case p of
            Request a' fa  -> Request a' (\a  -> go (fa  a ) w)
            Respond b  fb' -> Respond b  (\b' -> go (fb' b') w)
            M       m      -> M (do
                (p', w') <- listen m
                return (go p' $! mappend w w') )
            Pure    r      -> Pure (r, w)

    pass p0 = go p0 mempty
      where
        go p w = case p of
            Request a' fa  -> Request a' (\a  -> go (fa  a ) w)
            Respond b  fb' -> Respond b  (\b' -> go (fb' b') w)
            M       m      -> M (do
                (p', w') <- censor (const mempty) (listen m)
                return (go p' $! mappend w w') )
            Pure   (r, f)  -> M (pass (return (Pure r, \_ -> f w)))

instance MonadError e m => MonadError e (Proxy a' a b' b m) where
    throwError = lift . throwError
    catchError p0 f = go p0
      where
        go p = case p of
            Request a' fa  -> Request a' (\a  -> go (fa  a ))
            Respond b  fb' -> Respond b  (\b' -> go (fb' b'))
            Pure    r      -> Pure r
            M          m   -> M ((do
                p' <- m
                return (go p') ) `catchError` (\e -> return (f e)) )

instance MonadThrow m => MonadThrow (Proxy a' a b' b m) where
    throwM = lift . throwM
    {-# INLINE throwM #-}

instance MonadCatch m => MonadCatch (Proxy a' a b' b m) where
    catch p0 f = go p0
      where
        go p = case p of
            Request a' fa  -> Request a' (\a  -> go (fa  a ))
            Respond b  fb' -> Respond b  (\b' -> go (fb' b'))
            Pure    r      -> Pure r
            M          m   -> M ((do
                p' <- m
                return (go p') ) `Control.Monad.Catch.catch` (\e -> return (f e)) )

{-| The monad transformer laws are correct when viewed through the 'observe'
    function:

@
'observe' ('lift' ('return' r)) = 'observe' ('return' r)

'observe' ('lift' (m '>>=' f)) = 'observe' ('lift' m '>>=' 'lift' '.' f)
@

    This correctness comes at a small cost to performance, so use this function
    sparingly.

    This function is a convenience for low-level @pipes@ implementers.  You do
    not need to use 'observe' if you stick to the safe API.
-}
observe :: Monad m => Proxy a' a b' b m r -> Proxy a' a b' b m r
observe p0 = M (go p0) where
    go p = case p of
        Request a' fa  -> return (Request a' (\a  -> observe (fa  a )))
        Respond b  fb' -> return (Respond b  (\b' -> observe (fb' b')))
        M          m'  -> m' >>= go
        Pure    r      -> return (Pure r)
{-# INLINABLE observe #-}

-- | The empty type, used to close output ends
type X = Void

-- | Use 'closed' to \"handle\" impossible outputs
closed :: X -> a
closed = Data.Void.absurd
{-# INLINABLE closed #-}


================================================
FILE: src/Pipes/Lift.hs
================================================
{-# LANGUAGE CPP #-}

{-| Many actions in base monad transformers cannot be automatically
    'Control.Monad.Trans.Class.lift'ed.  These functions lift these remaining
    actions so that they work in the 'Proxy' monad transformer.

    See the mini-tutorial at the bottom of this module for example code and
    typical use cases where this module will come in handy.
-}

module Pipes.Lift (
    -- * Utilities
      distribute

    -- * ExceptT
    , exceptP
    , runExceptP
    , catchError
    , liftCatchError

    -- * MaybeT
    , maybeP
    , runMaybeP

    -- * ReaderT
    , readerP
    , runReaderP

    -- * StateT
    , stateP
    , runStateP
    , evalStateP
    , execStateP

    -- * WriterT
    -- $writert
    , writerP
    , runWriterP
    , execWriterP

    -- * RWST
    , rwsP
    , runRWSP
    , evalRWSP
    , execRWSP

    -- * Tutorial
    -- $tutorial
    ) where

import Control.Monad.Trans.Class (lift, MonadTrans(..))
import qualified Control.Monad.Trans.Except as E
import qualified Control.Monad.Trans.Maybe as M
import qualified Control.Monad.Trans.Reader as R
import qualified Control.Monad.Trans.State.Strict as S
import qualified Control.Monad.Trans.Writer.Strict as W
import qualified Control.Monad.Trans.RWS.Strict as RWS
import Pipes.Internal (Proxy(..), unsafeHoist)
import Control.Monad.Morph (hoist, MFunctor(..))
import Pipes.Core (runEffect, request, respond, (//>), (>\\))

#if MIN_VERSION_base(4,8,0)
#else
import Data.Monoid
#endif

-- | Distribute 'Proxy' over a monad transformer
distribute
    ::  ( Monad m
        , MonadTrans t
        , MFunctor t
        , Monad (t m)
        , Monad (t (Proxy a' a b' b m))
        )
    => Proxy a' a b' b (t m) r
    -- ^ 
    -> t (Proxy a' a b' b m) r
    -- ^ 
distribute p =  runEffect $ request' >\\ unsafeHoist (hoist lift) p //> respond'
  where
    request' = lift . lift . request
    respond' = lift . lift . respond
{-# INLINABLE distribute #-}

-- | Wrap the base monad in 'E.ExceptT'
exceptP
    :: Monad m
    => Proxy a' a b' b m (Either e r)
    -> Proxy a' a b' b (E.ExceptT e m) r
exceptP p = do
    x <- unsafeHoist lift p
    lift $ E.ExceptT (return x)
{-# INLINABLE exceptP #-}

-- | Run 'E.ExceptT' in the base monad
runExceptP
    :: Monad m
    => Proxy a' a b' b (E.ExceptT e m) r
    -> Proxy a' a b' b m (Either e r)
runExceptP    = E.runExceptT . distribute
{-# INLINABLE runExceptP #-}

-- | Catch an error in the base monad
catchError
    :: Monad m
    => Proxy a' a b' b (E.ExceptT e m) r
    -- ^
    -> (e -> Proxy a' a b' b (E.ExceptT e m) r)
    -- ^
    -> Proxy a' a b' b (E.ExceptT e m) r
catchError e h = exceptP . E.runExceptT $ 
    E.catchE (distribute e) (distribute . h)
{-# INLINABLE catchError #-}

-- | Catch an error using a catch function for the base monad
liftCatchError
    :: Monad m
    => (   m (Proxy a' a b' b m r)
        -> (e -> m (Proxy a' a b' b m r))
        -> m (Proxy a' a b' b m r) )
    -- ^
    ->    (Proxy a' a b' b m r
        -> (e -> Proxy a' a b' b m r)
        -> Proxy a' a b' b m r)
    -- ^
liftCatchError c p0 f = go p0
  where
    go p = case p of
        Request a' fa  -> Request a' (\a  -> go (fa  a ))
        Respond b  fb' -> Respond b  (\b' -> go (fb' b'))
        Pure    r      -> Pure r
        M          m   -> M ((do
            p' <- m
            return (go p') ) `c` (\e -> return (f e)) )
{-# INLINABLE liftCatchError #-}

-- | Wrap the base monad in 'M.MaybeT'
maybeP
    :: Monad m
    => Proxy a' a b' b m (Maybe r) -> Proxy a' a b' b (M.MaybeT m) r
maybeP p = do
    x <- unsafeHoist lift p
    lift $ M.MaybeT (return x)
{-# INLINABLE maybeP #-}

-- | Run 'M.MaybeT' in the base monad
runMaybeP
    :: Monad m
    => Proxy a' a b' b (M.MaybeT m) r
    -> Proxy a' a b' b m (Maybe r)
runMaybeP p = M.runMaybeT $ distribute p
{-# INLINABLE runMaybeP #-}

-- | Wrap the base monad in 'R.ReaderT'
readerP
    :: Monad m
    => (i -> Proxy a' a b' b m r) -> Proxy a' a b' b (R.ReaderT i m) r
readerP k = do
    i <- lift R.ask
    unsafeHoist lift (k i)
{-# INLINABLE readerP #-}

-- | Run 'R.ReaderT' in the base monad
runReaderP
    :: Monad m
    => i
    -> Proxy a' a b' b (R.ReaderT i m) r
    -> Proxy a' a b' b m r
runReaderP r p = (`R.runReaderT` r) $ distribute p
{-# INLINABLE runReaderP #-}

-- | Wrap the base monad in 'S.StateT'
stateP
    :: Monad m
    => (s -> Proxy a' a b' b m (r, s)) -> Proxy a' a b' b (S.StateT s m) r
stateP k = do
    s <- lift S.get
    (r, s') <- unsafeHoist lift (k s)
    lift (S.put s')
    return r
{-# INLINABLE stateP #-}

-- | Run 'S.StateT' in the base monad
runStateP
    :: Monad m
    => s
    -> Proxy a' a b' b (S.StateT s m) r
    -> Proxy a' a b' b m (r, s)
runStateP s p = (`S.runStateT` s) $ distribute p
{-# INLINABLE runStateP #-}

-- | Evaluate 'S.StateT' in the base monad
evalStateP
    :: Monad m
    => s
    -> Proxy a' a b' b (S.StateT s m) r
    -> Proxy a' a b' b m r
evalStateP s p = fmap fst $ runStateP s p
{-# INLINABLE evalStateP #-}

-- | Execute 'S.StateT' in the base monad
execStateP
    :: Monad m
    => s
    -> Proxy a' a b' b (S.StateT s m) r
    -> Proxy a' a b' b m s
execStateP s p = fmap snd $ runStateP s p
{-# INLINABLE execStateP #-}

{- $writert
    Note that 'runWriterP' and 'execWriterP' will keep the accumulator in
    weak-head-normal form so that folds run in constant space when possible.

    This means that until @transformers@ adds a truly strict 'W.WriterT', you
    should consider unwrapping 'W.WriterT' first using 'runWriterP' or
    'execWriterP' before running your 'Proxy'.  You will get better performance
    this way and eliminate space leaks if your accumulator doesn't have any lazy
    fields.
-}

-- | Wrap the base monad in 'W.WriterT'
writerP
    :: (Monad m, Monoid w)
    => Proxy a' a b' b m (r, w) -> Proxy a' a b' b (W.WriterT w m) r
writerP p = do
    (r, w) <- unsafeHoist lift p
    lift $ W.tell w
    return r
{-# INLINABLE writerP #-}

-- | Run 'W.WriterT' in the base monad
runWriterP
    :: (Monad m, Monoid w)
    => Proxy a' a b' b (W.WriterT w m) r
    -> Proxy a' a b' b m (r, w)
runWriterP p = W.runWriterT $ distribute p
{-# INLINABLE runWriterP #-}

-- | Execute 'W.WriterT' in the base monad
execWriterP
    :: (Monad m, Monoid w)
    => Proxy a' a b' b (W.WriterT w m) r
    -> Proxy a' a b' b m w
execWriterP p = fmap snd $ runWriterP p
{-# INLINABLE execWriterP #-}

-- | Wrap the base monad in 'RWS.RWST'
rwsP
    :: (Monad m, Monoid w)
    => (i -> s -> Proxy a' a b' b m (r, s, w))
    -> Proxy a' a b' b (RWS.RWST i w s m) r
rwsP k = do
    i <- lift RWS.ask
    s <- lift RWS.get
    (r, s', w) <- unsafeHoist lift (k i s)
    lift $ do
        RWS.put s'
        RWS.tell w
    return r
{-# INLINABLE rwsP #-}

-- | Run 'RWS.RWST' in the base monad
runRWSP
    :: (Monad m, Monoid w)
    => r
    -> s
    -> Proxy a' a b' b (RWS.RWST r w s m) d
    -> Proxy a' a b' b m (d, s, w)
runRWSP  i s p = (\b -> RWS.runRWST b i s) $ distribute p
{-# INLINABLE runRWSP #-}

-- | Evaluate 'RWS.RWST' in the base monad
evalRWSP
    :: (Monad m, Monoid w)
    => r
    -> s
    -> Proxy a' a b' b (RWS.RWST r w s m) d
    -> Proxy a' a b' b m (d, w)
evalRWSP i s p = fmap f $ runRWSP i s p
  where
    f x = let (r, _, w) = x in (r, w)
{-# INLINABLE evalRWSP #-}

-- | Execute 'RWS.RWST' in the base monad
execRWSP
    :: (Monad m, Monoid w)
    => r
    -> s
    -> Proxy a' a b' b (RWS.RWST r w s m) d
    -> Proxy a' a b' b m (s, w)
execRWSP i s p = fmap f $ runRWSP i s p
  where
    f x = let (_, s', w) = x in (s', w)
{-# INLINABLE execRWSP #-}

{- $tutorial
    Probably the most useful functionality in this module is lifted error
    handling.  Suppose that you have a 'Pipes.Pipe' whose base monad can fail
    using 'E.ExceptT':

> import Control.Monad.Trans.Error
> import Pipes
>
> example :: Monad m => Pipe Int Int (ExceptT String m) r
> example = for cat $ \n ->
>     if n == 0
>     then lift $ throwError "Zero is forbidden"
>     else yield n

    Without the tools in this module you cannot recover from any potential error
    until after you compose and run the pipeline:

>>> import qualified Pipes.Prelude as P
>>> runExceptT $ runEffect $ P.readLn >-> example >-> P.print
42<Enter>
42
1<Enter>
1
0<Enter>
Zero is forbidden
>>>

    This module provides `catchError`, which lets you catch and recover from
    errors inside the 'Pipe':

>  import qualified Pipes.Lift as Lift
> 
>  caught :: Pipe Int Int (ExceptT String IO) r
>  caught = example `Lift.catchError` \str -> do
>      liftIO (putStrLn str)
>      caught

    This lets you resume streaming in the face of errors raised within the base
    monad:

>>> runExceptT $ runEffect $ P.readLn >-> caught >-> P.print
0<Enter>
Zero is forbidden
42<Enter>
42
0<Enter>
Zero is forbidden
1<Enter>
1
...

    Another common use case is running a base monad before running the pipeline.
    For example, the following contrived 'Producer' uses 'S.StateT' gratuitously
    to increment numbers:

> import Control.Monad (forever)
> import Control.Monad.Trans.State.Strict
> import Pipes
> 
> numbers :: Monad m => Producer Int (StateT Int m) r
> numbers = forever $ do
>     n <- lift get
>     yield n
>     lift $ put $! n + 1

    You can run the 'StateT' monad by supplying an initial state, before you
    ever compose the 'Producer':

> import Pipes.Lift
>
> naturals :: Monad m => Producer Int m r
> naturals = evalStateP 0 numbers

    This deletes 'StateT' from the base monad entirely, give you a completely
    pure 'Pipes.Producer':

>>> Pipes.Prelude.toList naturals
[0,1,2,3,4,5,6...]

    Note that the convention for the 'S.StateT' run functions is backwards from
    @transformers@ for convenience: the initial state is the first argument.

    All of these functions internally use 'distribute', which can pull out most
    monad transformers from the base monad.  For example, 'evalStateP' is
    defined in terms of 'distribute':

> evalStateP s p = evalStateT (distribute p) s

    Therefore you can use 'distribute' to run other monad transformers, too, as
    long as they implement the 'MFunctor' type class from the @mmorph@ library.
-}


================================================
FILE: src/Pipes/Prelude.hs
================================================
{-| General purpose utilities

    The names in this module clash heavily with the Haskell Prelude, so I
    recommend the following import scheme:

> import Pipes
> import qualified Pipes.Prelude as P  -- or use any other qualifier you prefer

    Note that 'String'-based 'IO' is inefficient.  The 'String'-based utilities
    in this module exist only for simple demonstrations without incurring a
    dependency on the @text@ package.

    Also, 'stdinLn' and 'stdoutLn' remove and add newlines, respectively.  This
    behavior is intended to simplify examples.  The corresponding @stdin@ and
    @stdout@ utilities from @pipes-bytestring@ and @pipes-text@ preserve
    newlines.
-}

{-# LANGUAGE RankNTypes, Trustworthy #-}
{-# OPTIONS_GHC -fno-warn-unused-do-bind #-}

module Pipes.Prelude (
    -- * Producers
    -- $producers
      stdinLn
    , readLn
    , fromHandle
    , repeatM
    , replicateM
    , unfoldr

    -- * Consumers
    -- $consumers
    , stdoutLn
    , stdoutLn'
    , mapM_
    , print
    , toHandle
    , drain

    -- * Pipes
    -- $pipes
    , map
    , mapM
    , sequence
    , mapFoldable
    , filter
    , mapMaybe
    , filterM
    , wither
    , take
    , takeWhile
    , takeWhile'
    , drop
    , dropWhile
    , concat
    , elemIndices
    , findIndices
    , scan
    , scanM
    , chain
    , read
    , show
    , seq

    -- *ListT
    , loop

    -- * 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

    -- * Utilities
    , tee
    , generalize
    ) where

import Control.Exception (throwIO, try)
import Control.Monad (liftM, when, unless, (>=>))
import Control.Monad.Trans.State.Strict (get, put)
import Data.Functor.Identity (Identity, runIdentity)
import Foreign.C.Error (Errno(Errno), ePIPE)
import GHC.Exts (build)
import Pipes
import Pipes.Core
import Pipes.Internal
import Pipes.Lift (evalStateP)
import qualified GHC.IO.Exception as G
import qualified System.IO as IO
import qualified Prelude
import Prelude hiding (
      all
    , and
    , any
    , concat
    , drop
    , dropWhile
    , elem
    , filter
    , head
    , last
    , length
    , map
    , mapM
    , mapM_
    , maximum
    , minimum
    , notElem
    , null
    , or
    , print
    , product
    , read
    , readLn
    , sequence
    , show
    , seq
    , sum
    , take
    , takeWhile
    , zip
    , zipWith
    )

{- $producers
    Use 'for' loops to iterate over 'Producer's whenever you want to perform the
    same action for every element:

> -- Echo all lines from standard input to standard output
> runEffect $ for P.stdinLn $ \str -> do
>     lift $ putStrLn str

    ... or more concisely:

>>> runEffect $ for P.stdinLn (lift . putStrLn)
Test<Enter>
Test
ABC<Enter>
ABC
...

-}

{-| Read 'String's from 'IO.stdin' using 'getLine'

    Terminates on end of input
-}
stdinLn :: MonadIO m => Producer' String m ()
stdinLn = fromHandle IO.stdin
{-# INLINABLE stdinLn #-}

-- | 'read' values from 'IO.stdin', ignoring failed parses
readLn :: (MonadIO m, Read a) => Producer' a m ()
readLn = stdinLn >-> read
{-# INLINABLE readLn #-}

{-| Read 'String's from a 'IO.Handle' using 'IO.hGetLine'

    Terminates on end of input

@
'fromHandle' :: 'MonadIO' m => 'IO.Handle' -> 'Producer' 'String' m ()
@
-}
fromHandle :: MonadIO m => IO.Handle -> Proxy x' x () String m ()
fromHandle h = go
  where
    go = do
        eof <- liftIO $ IO.hIsEOF h
        unless eof $ do
            str <- liftIO $ IO.hGetLine h
            yield str
            go
{-# INLINABLE fromHandle #-}

{-| Repeat a monadic action indefinitely, 'yield'ing each result

'repeatM' :: 'Monad' m => m a -> 'Producer' a m r
-}
repeatM :: Monad m => m a -> Proxy x' x () a m r
repeatM m = lift m >~ cat
{-# INLINABLE [1] repeatM #-}

{-# RULES
  "repeatM m >-> p" forall m p . repeatM m >-> p = lift m >~ p
  #-}

{-| Repeat a monadic action a fixed number of times, 'yield'ing each result

> replicateM  0      x = return ()
>
> replicateM (m + n) x = replicateM m x >> replicateM n x  -- 0 <= {m,n}

@
'replicateM' :: 'Monad' m => Int -> m a -> 'Producer' a m ()
@
-}
replicateM :: Monad m => Int -> m a -> Proxy x' x () a m ()
replicateM n m = lift m >~ take n
{-# INLINABLE replicateM #-}

{- $consumers
    Feed a 'Consumer' the same value repeatedly using ('>~'):

>>> runEffect $ lift getLine >~ P.stdoutLn
Test<Enter>
Test
ABC<Enter>
ABC
...

-}

{-| Write 'String's to 'IO.stdout' using 'putStrLn'

    Unlike 'toHandle', 'stdoutLn' gracefully terminates on a broken output pipe
-}
stdoutLn :: MonadIO m => Consumer' String m ()
stdoutLn = go
  where
    go = do
        str <- await
        x   <- liftIO $ try (putStrLn str)
        case x of
           Left (G.IOError { G.ioe_type  = G.ResourceVanished
                           , G.ioe_errno = Just ioe })
                | Errno ioe == ePIPE
                    -> return ()
           Left  e  -> liftIO (throwIO e)
           Right () -> go
{-# INLINABLE stdoutLn #-}

{-| Write 'String's to 'IO.stdout' using 'putStrLn'

    This does not handle a broken output pipe, but has a polymorphic return
    value
-}
stdoutLn' :: MonadIO m => Consumer' String m r
stdoutLn' = for cat (\str -> liftIO (putStrLn str))
{-# INLINABLE [1] stdoutLn' #-}

{-# RULES
    "p >-> stdoutLn'" forall p .
        p >-> stdoutLn' = for p (\str -> liftIO (putStrLn str))
  #-}

-- | Consume all values using a monadic function
mapM_ :: Monad m => (a -> m ()) -> Consumer' a m r
mapM_ f = for cat (\a -> lift (f a))
{-# INLINABLE [1] mapM_ #-}

{-# RULES
    "p >-> mapM_ f" forall p f .
        p >-> mapM_ f = for p (\a -> lift (f a))
  #-}

-- | 'print' values to 'IO.stdout'
print :: (MonadIO m, Show a) => Consumer' a m r
print = for cat (\a -> liftIO (Prelude.print a))
{-# INLINABLE [1] print #-}

{-# RULES
    "p >-> print" forall p .
        p >-> print = for p (\a -> liftIO (Prelude.print a))
  #-}

-- | Write 'String's to a 'IO.Handle' using 'IO.hPutStrLn'
toHandle :: MonadIO m => IO.Handle -> Consumer' String m r
toHandle handle = for cat (\str -> liftIO (IO.hPutStrLn handle str))
{-# INLINABLE [1] toHandle #-}

{-# RULES
    "p >-> toHandle handle" forall p handle .
        p >-> toHandle handle = for p (\str -> liftIO (IO.hPutStrLn handle str))
  #-}

-- | 'discard' all incoming values
drain :: Functor m => Consumer' a m r
drain = for cat discard
{-# INLINABLE [1] drain #-}

{-# RULES
    "p >-> drain" forall p .
        p >-> drain = for p discard
  #-}

{- $pipes
    Use ('>->') to connect 'Producer's, 'Pipe's, and 'Consumer's:

>>> runEffect $ P.stdinLn >-> P.takeWhile (/= "quit") >-> P.stdoutLn
Test<Enter>
Test
ABC<Enter>
ABC
quit<Enter>
>>>

-}

{-| Apply a function to all values flowing downstream

> map id = cat
>
> map (g . f) = map f >-> map g
-}
map :: Functor m => (a -> b) -> Pipe a b m r
map f = for cat (\a -> yield (f a))
{-# INLINABLE [1] map #-}

{-# RULES
    "p >-> map f" forall p f . p >-> map f = for p (\a -> yield (f a))

  ; "map f >-> p" forall p f . map f >-> p = (do
        a <- await
        return (f a) ) >~ p
  #-}

{-| Apply a monadic function to all values flowing downstream

> mapM return = cat
>
> mapM (f >=> g) = mapM f >-> mapM g
-}
mapM :: Monad m => (a -> m b) -> Pipe a b m r
mapM f = for cat $ \a -> do
    b <- lift (f a)
    yield b
{-# INLINABLE [1] mapM #-}

{-# RULES
    "p >-> mapM f" forall p f . p >-> mapM f = for p (\a -> do
        b <- lift (f a)
        yield b )

  ; "mapM f >-> p" forall p f . mapM f >-> p = (do
        a <- await
        b <- lift (f a)
        return b ) >~ p
  #-}

-- | Convert a stream of actions to a stream of values
sequence :: Monad m => Pipe (m a) a m r
sequence = mapM id
{-# INLINABLE sequence #-}

{- | Apply a function to all values flowing downstream, and
     forward each element of the result.
-}
mapFoldable :: (Functor m, Foldable t) => (a -> t b) -> Pipe a b m r
mapFoldable f = for cat (\a -> each (f a))
{-# INLINABLE [1] mapFoldable #-}

{-# RULES
    "p >-> mapFoldable f" forall p f .
        p >-> mapFoldable f = for p (\a -> each (f a))
  #-}

{-| @(filter predicate)@ only forwards values that satisfy the predicate.

> filter (pure True) = cat
>
> filter (liftA2 (&&) p1 p2) = filter p1 >-> filter p2
>
> filter f = mapMaybe (\a -> a <$ guard (f a))
-}
filter :: Functor m => (a -> Bool) -> Pipe a a m r
filter predicate = for cat $ \a -> when (predicate a) (yield a)
{-# INLINABLE [1] filter #-}

{-# RULES
    "p >-> filter predicate" forall p predicate.
        p >-> filter predicate = for p (\a -> when (predicate a) (yield a))
  #-}

{-| @(mapMaybe f)@ yields 'Just' results of 'f'.

Basic laws:

> mapMaybe (f >=> g) = mapMaybe f >-> mapMaybe g
>
> mapMaybe (pure @Maybe . f) = mapMaybe (Just . f) = map f
>
> mapMaybe (const Nothing) = drain

As a result of the second law,

> mapMaybe return = mapMaybe Just = cat
-}
mapMaybe :: Functor m => (a -> Maybe b) -> Pipe a b m r
mapMaybe f = for cat $ maybe (pure ()) yield . f
{-# INLINABLE [1] mapMaybe #-}

{-# RULES
    "p >-> mapMaybe f" forall p f.
        p >-> mapMaybe f = for p $ maybe (pure ()) yield . f
  #-}

{-| @(filterM predicate)@ only forwards values that satisfy the monadic
    predicate

> filterM (pure (pure True)) = cat
>
> filterM (liftA2 (liftA2 (&&)) p1 p2) = filterM p1 >-> filterM p2
>
> filterM f = wither (\a -> (\b -> a <$ guard b) <$> f a)
-}
filterM :: Monad m => (a -> m Bool) -> Pipe a a m r
filterM predicate = for cat $ \a -> do
    b <- lift (predicate a)
    when b (yield a)
{-# INLINABLE [1] filterM #-}

{-# RULES
    "p >-> filterM predicate" forall p predicate .
        p >-> filterM predicate = for p (\a -> do
            b <- lift (predicate a)
            when b (yield a) )
  #-}

{-| @(wither f)@ forwards 'Just' values produced by the
    monadic action.

Basic laws:

> wither (runMaybeT . (MaybeT . f >=> MaybeT . g)) = wither f >-> wither g
>
> wither (runMaybeT . lift . f) = wither (fmap Just . f) = mapM f
>
> wither (pure . f) = mapMaybe f

As a result of the second law,

> wither (runMaybeT . return) = cat

As a result of the third law,

> wither (pure . const Nothing) = wither (const (pure Nothing)) = drain
-}
wither :: Monad m => (a -> m (Maybe b)) -> Pipe a b m r
wither f = for cat $ lift . f >=> maybe (pure ()) yield
{-# INLINABLE [1] wither #-}

{-# RULES
    "p >-> wither f" forall p f .
        p >-> wither f = for p $ lift . f >=> maybe (pure ()) yield
  #-}

{-| @(take n)@ only allows @n@ values to pass through

> take 0 = return ()
>
> take (m + n) = take m >> take n

> take <infinity> = cat
>
> take (min m n) = take m >-> take n
-}
take :: Functor m => Int -> Pipe a a m ()
take = go
  where
    go 0 = return () 
    go n = do 
        a <- await
        yield a
        go (n-1)
{-# INLINABLE take #-}

{-| @(takeWhile p)@ allows values to pass downstream so long as they satisfy
    the predicate @p@.

> takeWhile (pure True) = cat
>
> takeWhile (liftA2 (&&) p1 p2) = takeWhile p1 >-> takeWhile p2
-}
takeWhile :: Functor m => (a -> Bool) -> Pipe a a m ()
takeWhile predicate = go
  where
    go = do
        a <- await
        if (predicate a)
            then do
                yield a
                go
            else return ()
{-# INLINABLE takeWhile #-}

{-| @(takeWhile' p)@ is a version of takeWhile that returns the value failing
    the predicate.

> takeWhile' (pure True) = cat
>
> takeWhile' (liftA2 (&&) p1 p2) = takeWhile' p1 >-> takeWhile' p2
-}
takeWhile' :: Functor m => (a -> Bool) -> Pipe a a m a
takeWhile' predicate = go
  where
    go = do
        a <- await
        if (predicate a)
            then do
                yield a
                go
            else return a
{-# INLINABLE takeWhile' #-}

{-| @(drop n)@ discards @n@ values going downstream

> drop 0 = cat
>
> drop (m + n) = drop m >-> drop n
-}
drop :: Functor m => Int -> Pipe a a m r
drop = go
  where
    go 0 = cat
    go n =  do
        await
        go (n-1)
{-# INLINABLE drop #-}

{-| @(dropWhile p)@ discards values going downstream until one violates the
    predicate @p@.

> dropWhile (pure False) = cat
>
> dropWhile (liftA2 (||) p1 p2) = dropWhile p1 >-> dropWhile p2
-}
dropWhile :: Functor m => (a -> Bool) -> Pipe a a m r
dropWhile predicate = go
  where
    go = do
        a <- await
        if (predicate a)
            then go
            else do
                yield a
                cat
{-# INLINABLE dropWhile #-}

-- | Flatten all 'Foldable' elements flowing downstream
concat :: (Functor m, Foldable f) => Pipe (f a) a m r
concat = for cat each
{-# INLINABLE [1] concat #-}

{-# RULES
    "p >-> concat" forall p . p >-> concat = for p each
  #-}

-- | Outputs the indices of all elements that match the given element
elemIndices :: (Functor m, Eq a) => a -> Pipe a Int m r
elemIndices a = findIndices (a ==)
{-# INLINABLE elemIndices #-}

-- | Outputs the indices of all elements that satisfied the predicate
findIndices :: Functor m => (a -> Bool) -> Pipe a Int m r
findIndices predicate = go 0
  where
    go n = do
        a <- await
        when (predicate a) (yield n)
        go $! n + 1
{-# INLINABLE findIndices #-}

{-| Strict left scan

> Control.Foldl.purely scan :: Monad m => Fold a b -> Pipe a b m r
-}
scan :: Functor m => (x -> a -> x) -> x -> (x -> b) -> Pipe a b m r
scan step begin done = go begin
  where
    go x = do
        yield (done x)
        a <- await
        let x' = step x a
        go $! x'
{-# INLINABLE scan #-}

{-| Strict, monadic left scan

> Control.Foldl.impurely scanM :: Monad m => FoldM m a b -> Pipe a b m r
-}
scanM :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> Pipe a b m r
scanM step begin done = do
    x <- lift begin
    go x
  where
    go x = do
        b <- lift (done x)
        yield b
        a  <- await
        x' <- lift (step x a)
        go $! x'
{-# INLINABLE scanM #-}

{-| Apply an action to all values flowing downstream

> chain (pure (return ())) = cat
>
> chain (liftA2 (>>) m1 m2) = chain m1 >-> chain m2
-}
chain :: Monad m => (a -> m ()) -> Pipe a a m r
chain f = for cat $ \a -> do
    lift (f a)
    yield a
{-# INLINABLE [1] chain #-}

{-# RULES
    "p >-> chain f" forall p f .
        p >-> chain f = for p (\a -> do
            lift (f a)
            yield a )
  ; "chain f >-> p" forall p f .
        chain f >-> p = (do
            a <- await
            lift (f a)
            return a ) >~ p
  #-}

-- | Parse 'Read'able values, only forwarding the value if the parse succeeds
read :: (Functor m, Read a) => Pipe String a m r
read = for cat $ \str -> case (reads str) of
    [(a, "")] -> yield a
    _         -> return ()
{-# INLINABLE [1] read #-}

{-# RULES
    "p >-> read" forall p .
        p >-> read = for p (\str -> case (reads str) of
            [(a, "")] -> yield a
            _         -> return () )
  #-}

-- | Convert 'Show'able values to 'String's
show :: (Functor m, Show a) => Pipe a String m r
show = map Prelude.show
{-# INLINABLE show #-}

-- | Evaluate all values flowing downstream to WHNF
seq :: Functor m => Pipe a a m r
seq = for cat $ \a -> yield $! a
{-# INLINABLE seq #-}

{-| Create a `Pipe` from a `ListT` transformation

> loop (k1 >=> k2) = loop k1 >-> loop k2
>
> loop return = cat
-}
loop :: Monad m => (a -> ListT m b) -> Pipe a b m r
loop k = for cat (every . k)
{-# INLINABLE loop #-}

{- $folds
    Use these to fold the output of a 'Producer'.  Many of these folds will stop
    drawing elements if they can compute their result early, like 'any':

>>> P.any Prelude.null P.stdinLn
Test<Enter>
ABC<Enter>
<Enter>
True
>>>

-}

{-| Strict fold of the elements of a 'Producer'

> Control.Foldl.purely fold :: Monad m => Fold a b -> Producer a m () -> m b
-}
fold :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Producer a m () -> m b
fold step begin done p0 = go p0 begin
  where
    go p x = case p of
        Request v  _  -> closed v
        Respond a  fu -> go (fu ()) $! step x a
        M          m  -> m >>= \p' -> go p' x
        Pure    _     -> return (done x)
{-# INLINABLE fold #-}

{-| Strict fold of the elements of a 'Producer' that preserves the return value

> Control.Foldl.purely fold' :: Monad m => Fold a b -> Producer a m r -> m (b, r)
-}
fold' :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Producer a m r -> m (b, r)
fold' step begin done p0 = go p0 begin
  where
    go p x = case p of
        Request v  _  -> closed v
        Respond a  fu -> go (fu ()) $! step x a
        M          m  -> m >>= \p' -> go p' x
        Pure    r     -> return (done x, r)
{-# INLINABLE fold' #-}

{-| Strict, monadic fold of the elements of a 'Producer'

> Control.Foldl.impurely foldM :: Monad m => FoldM a b -> Producer a m () -> m b
-}
foldM
    :: Monad m
    => (x -> a -> m x) -> m x -> (x -> m b) -> Producer a m () -> m b
foldM step begin done p0 = do
    x0 <- begin
    go p0 x0
  where
    go p x = case p of
        Request v  _  -> closed v
        Respond a  fu -> do
            x' <- step x a
            go (fu ()) $! x'
        M          m  -> m >>= \p' -> go p' x
        Pure    _     -> done x
{-# INLINABLE foldM #-}

{-| Strict, monadic fold of the elements of a 'Producer'

> Control.Foldl.impurely foldM' :: Monad m => FoldM a b -> Producer a m r -> m (b, r)
-}
foldM'
    :: Monad m
    => (x -> a -> m x) -> m x -> (x -> m b) -> Producer a m r -> m (b, r)
foldM' step begin done p0 = do
    x0 <- begin
    go p0 x0
  where
    go p x = case p of
        Request v  _  -> closed v
        Respond a  fu -> do
            x' <- step x a
            go (fu ()) $! x'
        M          m  -> m >>= \p' -> go p' x
        Pure    r     -> do
            b <- done x
            return (b, r)
{-# INLINABLE foldM' #-}

{-| @(all predicate p)@ determines whether all the elements of @p@ satisfy the
    predicate.
-}
all :: Monad m => (a -> Bool) -> Producer a m () -> m Bool
all predicate p = null $ p >-> filter (\a -> not (predicate a))
{-# INLINABLE all #-}

{-| @(any predicate p)@ determines whether any element of @p@ satisfies the
    predicate.
-}
any :: Monad m => (a -> Bool) -> Producer a m () -> m Bool
any predicate p = liftM not $ null (p >-> filter predicate)
{-# INLINABLE any #-}

-- | Determines whether all elements are 'True'
and :: Monad m => Producer Bool m () -> m Bool
and = all id
{-# INLINABLE and #-}

-- | Determines whether any element is 'True'
or :: Monad m => Producer Bool m () -> m Bool
or = any id
{-# INLINABLE or #-}

{-| @(elem a p)@ returns 'True' if @p@ has an element equal to @a@, 'False'
    otherwise
-}
elem :: (Monad m, Eq a) => a -> Producer a m () -> m Bool
elem a = any (a ==)
{-# INLINABLE elem #-}

{-| @(notElem a)@ returns 'False' if @p@ has an element equal to @a@, 'True'
    otherwise
-}
notElem :: (Monad m, Eq a) => a -> Producer a m () -> m Bool
notElem a = all (a /=)
{-# INLINABLE notElem #-}

-- | Find the first element of a 'Producer' that satisfies the predicate
find :: Monad m => (a -> Bool) -> Producer a m () -> m (Maybe a)
find predicate p = head (p >-> filter predicate)
{-# INLINABLE find #-}

{-| Find the index of the first element of a 'Producer' that satisfies the
    predicate
-}
findIndex :: Monad m => (a -> Bool) -> Producer a m () -> m (Maybe Int)
findIndex predicate p = head (p >-> findIndices predicate)
{-# INLINABLE findIndex #-}

-- | Retrieve the first element from a 'Producer'
head :: Monad m => Producer a m () -> m (Maybe a)
head p = do
    x <- next p
    return $ case x of
        Left   _     -> Nothing
        Right (a, _) -> Just a
{-# INLINABLE head #-}

-- | Index into a 'Producer'
index :: Monad m => Int -> Producer a m () -> m (Maybe a)
index n p = head (p >-> drop n)
{-# INLINABLE index #-}

-- | Retrieve the last element from a 'Producer'
last :: Monad m => Producer a m () -> m (Maybe a)
last p0 = do
    x <- next p0
    case x of
        Left   _      -> return Nothing
        Right (a, p') -> go a p'
  where
    go a p = do
        x <- next p
        case x of
            Left   _       -> return (Just a)
            Right (a', p') -> go a' p'
{-# INLINABLE last #-}

-- | Count the number of elements in a 'Producer'
length :: Monad m => Producer a m () -> m Int
length = fold (\n _ -> n + 1) 0 id
{-# INLINABLE length #-}

-- | Find the maximum element of a 'Producer'
maximum :: (Monad m, Ord a) => Producer a m () -> m (Maybe a)
maximum = fold step Nothing id
  where
    step x a = Just $ case x of
        Nothing -> a
        Just a' -> max a a'
{-# INLINABLE maximum #-}

-- | Find the minimum element of a 'Producer'
minimum :: (Monad m, Ord a) => Producer a m () -> m (Maybe a)
minimum = fold step Nothing id
  where
    step x a = Just $ case x of
        Nothing -> a
        Just a' -> min a a'
{-# INLINABLE minimum #-}

-- | Determine if a 'Producer' is empty
null :: Monad m => Producer a m () -> m Bool
null p = do
    x <- next p
    return $ case x of
        Left  _ -> True
        Right _ -> False
{-# INLINABLE null #-}

-- | Compute the sum of the elements of a 'Producer'
sum :: (Monad m, Num a) => Producer a m () -> m a
sum = fold (+) 0 id
{-# INLINABLE sum #-}

-- | Compute the product of the elements of a 'Producer'
product :: (Monad m, Num a) => Producer a m () -> m a
product = fold (*) 1 id
{-# INLINABLE product #-}

-- | Convert a pure 'Producer' into a list
toList :: Producer a Identity () -> [a]
toList prod0 = build (go prod0)
  where
    go prod cons nil =
      case prod of
        Request v _  -> closed v
        Respond a fu -> cons a (go (fu ()) cons nil)
        M         m  -> go (runIdentity m) cons nil
        Pure    _    -> nil
{-# INLINE toList #-}

{-| Convert an effectful 'Producer' into a list

    Note: 'toListM' is not an idiomatic use of @pipes@, but I provide it for
    simple testing purposes.  Idiomatic @pipes@ style consumes the elements
    immediately as they are generated instead of loading all elements into
    memory.
-}
toListM :: Monad m => Producer a m () -> m [a]
toListM = fold step begin done
  where
    step x a = x . (a:)
    begin = id
    done x = x []
{-# INLINABLE toListM #-}

{-| Convert an effectful 'Producer' into a list alongside the return value

    Note: 'toListM'' is not an idiomatic use of @pipes@, but I provide it for
    simple testing purposes.  Idiomatic @pipes@ style consumes the elements
    immediately as they are generated instead of loading all elements into
    memory.
-}
toListM' :: Monad m => Producer a m r -> m ([a], r)
toListM' = fold' step begin done
  where
    step x a = x . (a:)
    begin = id
    done x = x []
{-# INLINABLE toListM' #-}

-- | Zip two 'Producer's
zip :: Monad m
    => (Producer       a     m r)
    -> (Producer          b  m r)
    -> (Proxy x' x () (a, b) m r)
zip = zipWith (,)
{-# INLINABLE zip #-}

-- | Zip two 'Producer's using the provided combining function
zipWith :: Monad m
    => (a -> b -> c)
    -> (Producer  a m r)
    -> (Producer  b m r)
    -> (Proxy x' x () c m r)
zipWith f = go
  where
    go p1 p2 = do
        e1 <- lift $ next p1
        case e1 of
            Left r         -> return r
            Right (a, p1') -> do
                e2 <- lift $ next p2
                case e2 of
                    Left r         -> return r
                    Right (b, p2') -> do
                        yield (f a b)
                        go p1' p2'
{-# INLINABLE zipWith #-}

{-| Transform a 'Consumer' to a 'Pipe' that reforwards all values further
    downstream
-}
tee :: Monad m => Consumer a m r -> Pipe a a m r
tee p = evalStateP Nothing $ do
    r <- up >\\ (hoist lift p //> dn)
    ma <- lift get
    case ma of
        Nothing -> return ()
        Just a  -> yield a
    return r
  where
    up () = do
        ma <- lift get
        case ma of
            Nothing -> return ()
            Just a  -> yield a
        a <- await
        lift $ put (Just a)
        return a
    dn v = closed v
{-# INLINABLE tee #-}

{-| Transform a unidirectional 'Pipe' to a bidirectional 'Proxy'

> generalize (f >-> g) = generalize f >+> generalize g
>
> generalize cat = pull
-}
generalize :: Monad m => Pipe a b m r -> x -> Proxy x a x b m r
generalize p x0 = evalStateP x0 $ up >\\ hoist lift p //> dn
  where
    up () = do
        x <- lift get
        request x
    dn a = do
        x <- respond a
        lift $ put x
{-# INLINABLE generalize #-}

{-| The natural unfold into a 'Producer' with a step function and a seed 

> unfoldr next = id
-}
unfoldr :: Monad m 
        => (s -> m (Either r (a, s))) -> s -> Producer a m r
unfoldr step = go where
  go s0 = do
    e <- lift (step s0)
    case e of
      Left r -> return r
      Right (a,s) -> do 
        yield a
        go s
{-# INLINABLE unfoldr #-}


================================================
FILE: src/Pipes/Tutorial.hs
================================================
{-# OPTIONS_GHC -fno-warn-unused-imports #-}

{-| Conventional Haskell stream programming forces you to choose only two of the
    following three features:

    * Effects

    * Streaming

    * Composability

    If you sacrifice /Effects/ you get Haskell's pure and lazy lists, which you
    can transform using composable functions in constant space, but without
    interleaving effects.

    If you sacrifice /Streaming/ you get 'mapM', 'forM' and
    \"ListT done wrong\", which are composable and effectful, but do not return
    a single result until the whole list has first been processed and loaded
    into memory.

    If you sacrifice /Composability/ you write a tightly coupled read,
    transform, and write loop in 'IO', which is streaming and effectful, but is
    not modular or separable.

    @pipes@ gives you all three features: effectful, streaming, and composable
    programming.  @pipes@ also provides a wide variety of stream programming
    abstractions which are all subsets of a single unified machinery:

    * effectful 'Producer's (like generators),

    * effectful 'Consumer's (like iteratees),

    * effectful 'Pipe's (like Unix pipes), and:

    * 'ListT' done right.

    All of these are connectable and you can combine them together in clever and
    unexpected ways because they all share the same underlying type.

    @pipes@ requires a basic understanding of monad transformers, which you can
    learn about by reading either:

    * the paper \"Monad Transformers - Step by Step\",
    
    * part III \"Monads in the Real World\" of the tutorial \"All About Monads\",

    * chapter 18 of \"Real World Haskell\" on monad transformers, or:

    * the documentation of the @transformers@ library.

    If you want a Quick Start guide to @pipes@, read the documentation in
    "Pipes.Prelude" from top to bottom.

    This tutorial is more extensive and explains the @pipes@ API in greater
    detail and illustrates several idioms.
-}

module Pipes.Tutorial (
    -- * Introduction
    -- $introduction

    -- * Producers
    -- $producers

    -- * Composability
    -- $composability

    -- * Consumers
    -- $consumers

    -- * Pipes
    -- $pipes

    -- * ListT
    -- $listT

    -- * Tricks
    -- $tricks

    -- * Conclusion
    -- $conclusion

    -- * Appendix: Types
    -- $types

    -- * Appendix: Time Complexity
    -- $timecomplexity

    -- * Copyright
    -- $copyright
    ) where

import Control.Category
import Control.Monad
import Pipes
import qualified Pipes.Prelude as P
import Prelude hiding ((.), id)

{- $introduction
    The @pipes@ library decouples stream processing stages from each other so
    that you can mix and match diverse stages to produce useful streaming
    programs.  If you are a library writer, @pipes@ lets you package up
    streaming components into a reusable interface.  If you are an application
    writer, @pipes@ lets you connect pre-made streaming components with minimal
    effort to produce a highly-efficient program that streams data in constant
    memory.

    To enforce loose coupling, components can only communicate using two
    commands:

    * 'yield': Send output data

    * 'await': Receive input data

    @pipes@ has four types of components built around these two commands:

    * 'Producer's can only 'yield' values and they model streaming sources

    * 'Consumer's can only 'await' values and they model streaming sinks

    * 'Pipe's can both 'yield' and 'await' values and they model stream
      transformations

    * 'Effect's can neither 'yield' nor 'await' and they model non-streaming
      components

    You can connect these components together in four separate ways which
    parallel the four above types:

    * 'for' handles 'yield's

    * ('>~') handles 'await's

    * ('>->') handles both 'yield's and 'await's

    * ('>>=') handles return values

    As you connect components their types will change to reflect inputs and
    outputs that you've fused away.  You know that you're done connecting things
    when you get an 'Effect', meaning that you have handled all inputs and
    outputs.  You run this final 'Effect' to begin streaming.
-}

{- $producers
    'Producer's are effectful streams of input.  Specifically, a 'Producer' is a
    monad transformer that extends any base monad with a new 'yield' command.
    This 'yield' command lets you send output downstream to an anonymous
    handler, decoupling how you generate values from how you consume them.

    The following @stdinLn@ 'Producer' shows how to incrementally read in
    'String's from standard input and 'yield' them downstream, terminating
    gracefully when reaching the end of the input:

> -- echo.hs
>
> import Control.Monad (unless)
> import Pipes
> import System.IO (isEOF)
>
> --         +--------+-- A 'Producer' that yields 'String's
> --         |        |
> --         |        |      +-- Every monad transformer has a base monad.
> --         |        |      |   This time the base monad is 'IO'.
> --         |        |      |  
> --         |        |      |  +-- Every monadic action has a return value.
> --         |        |      |  |   This action returns '()' when finished
> --         v        v      v  v
> stdinLn :: Producer String IO ()
> stdinLn = do
>     eof <- lift isEOF        -- 'lift' an 'IO' action from the base monad
>     unless eof $ do
>         str <- lift getLine
>         yield str            -- 'yield' the 'String'
>         stdinLn              -- Loop

    'yield' emits a value, suspending the current 'Producer' until the value is
    consumed.  If nobody consumes the value (which is possible) then 'yield'
    never returns.  You can think of 'yield' as having the following type:

@
 'yield' :: 'Monad' m => a -> 'Producer' a m ()
@

    The true type of 'yield' is actually more general and powerful.  Throughout
    the tutorial I will present type signatures like this that are simplified at
    first and then later reveal more general versions.  So read the above type
    signature as simply saying: \"You can use 'yield' within a 'Producer', but
    you may be able to use 'yield' in other contexts, too.\"

    Click the link to 'yield' to navigate to its documentation.  There you will
    see that 'yield' actually uses the 'Producer'' (with an apostrophe) type
    synonym which hides a lot of polymorphism behind a simple veneer.  The
    documentation for 'yield' says that you can also use 'yield' within a
    'Pipe', too, because of this polymorphism:

@
 'yield' :: 'Monad' m => a -> 'Pipe' x a m ()
@

    Use simpler types like these to guide you until you understand the fully
    general type.

    'for' loops are the simplest way to consume a 'Producer' like @stdinLn@.
    'for' has the following type:

@
 \-\-                +-- Producer      +-- The body of the   +-- Result
 \-\-                |   to loop       |   loop              |
 \-\-                v   over          v                     v
 \-\-                --------------    ------------------    ----------
 'for' :: 'Monad' m => 'Producer' a m r -> (a -> 'Effect' m ()) -> 'Effect' m r
@

    @(for producer body)@ loops over @(producer)@, substituting each 'yield' in
    @(producer)@ with @(body)@.

    You can also deduce that behavior purely from the type signature:

    * The body of the loop takes exactly one argument of type @(a)@, which is
      the same as the output type of the 'Producer'.  Therefore, the body of the
      loop must get its input from that 'Producer' and nowhere else.

    * The return value of the input 'Producer' matches the return value of the
      result, therefore 'for' must loop over the entire 'Producer' and not skip
      anything.

    The above type signature is not the true type of 'for', which is actually
    more general.  Think of the above type signature as saying: \"If the first
    argument of 'for' is a 'Producer' and the second argument returns an
    'Effect', then the final result must be an 'Effect'.\"

    Click the link to 'for' to navigate to its documentation.  There you will
    see the fully general type and underneath you will see equivalent simpler
    types.  One of these says that if the body of the loop is a 'Producer', then
    the result is a 'Producer', too:

@
 'for' :: 'Monad' m => 'Producer' a m r -> (a -> 'Producer' b m ()) -> 'Producer' b m r
@

    The first type signature I showed for 'for' was a special case of this
    slightly more general signature because a 'Producer' that never 'yield's is
    also an 'Effect':

@
 data 'X'  -- The uninhabited type

\ type 'Effect' m r = 'Producer' 'X' m r
@

    This is why 'for' permits two different type signatures.  The first type
    signature is just a special case of the second one:

@
 'for' :: 'Monad' m => 'Producer' a m r -> (a -> 'Producer' b m ()) -> 'Producer' b m r

\ -- Specialize \'b\' to \'X\'
 'for' :: 'Monad' m => 'Producer' a m r -> (a -> 'Producer' 'X' m ()) -> 'Producer' 'X' m r

\ -- Producer X = Effect
 'for' :: 'Monad' m => 'Producer' a m r -> (a -> 'Effect'     m ()) -> 'Effect'     m r
@

    This is the same trick that all @pipes@ functions use to work with various
    combinations of 'Producer's, 'Consumer's, 'Pipe's, and 'Effect's.  Each
    function really has just one general type, which you can then simplify down
    to multiple useful alternative types.

    Here's an example use of a 'for' @loop@, where the second argument (the
    loop body) is an 'Effect':

> -- echo.hs
>
> loop :: Effect IO ()
> loop = for stdinLn $ \str -> do  -- Read this like: "for str in stdinLn"
>     lift $ putStrLn str          -- The body of the 'for' loop
>
> -- more concise: loop = for stdinLn (lift . putStrLn)

    In this example, 'for' loops over @stdinLn@ and replaces every 'yield' in
    @stdinLn@ with the body of the loop, printing each line.  This is exactly
    equivalent to the following code, which I've placed side-by-side with the
    original definition of @stdinLn@ for comparison:

> loop = do                      |  stdinLn = do
>     eof <- lift isEOF          |      eof <- lift isEOF
>     unless eof $ do            |      unless eof $ do
>         str <- lift getLine    |          str <- lift getLine
>         (lift . putStrLn) str  |          yield str
>         loop                   |          stdinLn

    You can think of 'yield' as creating a hole and a 'for' loop is one way to
    fill that hole.

    Notice how the final @loop@ only 'lift's actions from the base monad and
    does nothing else.  This property is true for all 'Effect's, which are just
    glorified wrappers around actions in the base monad.  This means we can run
    these 'Effect's to remove their 'lift's and lower them back to the
    equivalent computation in the base monad:

@
 'runEffect' :: 'Monad' m => 'Effect' m r -> m r
@

    This is the real type signature of 'runEffect', which refuses to accept
    anything other than an 'Effect'.  This ensures that we handle all inputs and
    outputs before streaming data:

> -- echo.hs
>
> main :: IO ()
> main = runEffect loop

    ... or you could inline the entire @loop@ into the following one-liner:

> main = runEffect $ for stdinLn (lift . putStrLn)

    Our final program loops over standard input and echoes every line to
    standard output until we hit @Ctrl-D@ to end the input stream:

> $ ghc -O2 echo.hs
> $ ./echo
> Test<Enter>
> Test
> ABC<Enter>
> ABC
> <Ctrl-D>
> $

    The final behavior is indistinguishable from just removing all the 'lift's
    from @loop@:

> main = do               |  loop = do
>     eof <- isEof        |      eof <- lift isEof
>     unless eof $ do     |      unless eof $ do
>         str <- getLine  |          str <- lift getLine
>         putStrLn str    |          (lift . putStrLn) str
>         main            |          loop

    This @main@ is what we might have written by hand if we were not using
    @pipes@, but with @pipes@ we can decouple the input and output logic from
    each other.  When we connect them back together, we still produce streaming
    code equivalent to what a sufficiently careful Haskell programmer would
    have written.

    You can also use 'for' to loop over lists, too.  To do so, convert the list
    to a 'Producer' using 'each', which is exported by default from "Pipes":

> each :: Monad m => [a] -> Producer a m ()
> each as = mapM_ yield as

    Combine 'for' and 'each' to iterate over lists using a \"foreach\" loop:

>>> runEffect $ for (each [1..4]) (lift . print)
1
2
3
4

    'each' is actually more general and works for any 'Foldable':

@
 'each' :: ('Monad' m, 'Foldable' f) => f a -> 'Producer' a m ()
@

     So you can loop over any 'Foldable' container or even a 'Maybe':

>>> runEffect $ for (each (Just 1)) (lift . print)
1

-}

{- $composability
    You might wonder why the body of a 'for' loop can be a 'Producer'.  Let's
    test out this feature by defining a new loop body that creates three copies
    of every value:

> -- nested.hs
>
> import Pipes
> import qualified Pipes.Prelude as P  -- Pipes.Prelude already has 'stdinLn'
> 
> triple :: Monad m => a -> Producer a m ()
> triple x = do
>     yield x
>     yield x
>     yield x
>
> loop :: Producer String IO ()
> loop = for P.stdinLn triple
>
> -- This is the exact same as:
> --
> -- loop = for P.stdinLn $ \x -> do
> --     yield x
> --     yield x
> --     yield x

    This time our @loop@ is a 'Producer' that outputs 'String's, specifically
    three copies of each line that we read from standard input.  Since @loop@ is
    a 'Producer' we cannot run it because there is still unhandled output.
    However, we can use yet another 'for' to handle this new repeated stream:

> -- nested.hs
>
> main = runEffect $ for loop (lift . putStrLn)

    This creates a program which echoes every line from standard input to
    standard output three times:

> $ ./nested
> Test<Enter>
> Test
> Test
> Test
> ABC<Enter>
> ABC
> ABC
> ABC
> <Ctrl-D>
> $

    But is this really necessary?  Couldn't we have instead written this using a
    nested for loop?

> main = runEffect $
>     for P.stdinLn $ \str1 ->
>         for (triple str1) $ \str2 ->
>             lift $ putStrLn str2

    Yes, we could have!  In fact, this is a special case of the following
    equality, which always holds no matter what:

@
 \-\- s :: Monad m =>      'Producer' a m ()  -- i.e. \'P.stdinLn\'
 \-\- f :: Monad m => a -> 'Producer' b m ()  -- i.e. \'triple\'
 \-\- g :: Monad m => b -> 'Producer' c m ()  -- i.e. \'(lift . putStrLn)\'

\ for (for s f) g = for s (\\x -> for (f x) g)
@

    We can understand the rationale behind this equality if we first define the
    following operator that is the point-free counterpart to 'for':

@
 (~>) :: Monad m
      => (a -> 'Producer' b m ())
      -> (b -> 'Producer' c m ())
      -> (a -> 'Producer' c m ())
 (f ~> g) x = for (f x) g
@

    Using ('~>') (pronounced \"into\"), we can transform our original equality
    into the following more symmetric equation:

@
 f :: Monad m => a -> 'Producer' b m ()
 g :: Monad m => b -> 'Producer' c m ()
 h :: Monad m => c -> 'Producer' d m ()

\ \-\- Associativity
 (f ~> g) ~> h = f ~> (g ~> h)
@

    This looks just like an associativity law.  In fact, ('~>') has another nice
    property, which is that 'yield' is its left and right identity:

> -- Left Identity
> yield ~> f = f

> -- Right Identity
> f ~> yield = f

    In other words, 'yield' and ('~>') form a 'Category', specifically the
    generator category, where ('~>') plays the role of the composition operator
    and 'yield' is the identity.  If you don't know what a 'Category' is, that's
    okay, and category theory is not a prerequisite for using @pipes@.  All you
    really need to know is that @pipes@ uses some simple category theory to keep
    the API intuitive and easy to use.

    Notice that if we translate the left identity law to use 'for' instead of
    ('~>') we get:

> for (yield x) f = f x

    This just says that if you iterate over a pure single-element 'Producer',
    then you could instead cut out the middle man and directly apply the body of
    the loop to that single element.

    If we translate the right identity law to use 'for' instead of ('~>') we
    get:

> for s yield = s

    This just says that if the only thing you do is re-'yield' every element of
    a stream, you get back your original stream.

    These three \"for loop\" laws summarize our intuition for how 'for' loops
    should behave and because these are 'Category' laws in disguise that means
    that 'Producer's are composable in a rigorous sense of the word.

    In fact, we get more out of this than just a bunch of equations.  We also
    get a useful operator: ('~>').  We can use this operator to condense
    our original code into the following more succinct form that composes two
    transformations:

> main = runEffect $ for P.stdinLn (triple ~> lift . putStrLn)

    This means that we can also choose to program in a more functional style and
    think of stream processing in terms of composing transformations using
    ('~>') instead of nesting a bunch of 'for' loops.

    The above example is a microcosm of the design philosophy behind the @pipes@
    library:

    * Define the API in terms of categories

    * Specify expected behavior in terms of category laws

    * Think compositionally instead of sequentially
-}

{- $consumers
    Sometimes you don't want to use a 'for' loop because you don't want to consume
    every element of a 'Producer' or because you don't want to process every
    value of a 'Producer' the exact same way.

    The most general solution is to externally iterate over the 'Producer' using
    the 'next' command:

@
 'next' :: 'Monad' m => 'Producer' a m r -> m ('Either' r (a, 'Producer' a m r))
@

    Think of 'next' as pattern matching on the head of the 'Producer'.  This
    'Either' returns a 'Left' if the 'Producer' is done or it returns a 'Right'
    containing the next value, @a@, along with the remainder of the 'Producer'.

    However, sometimes we can get away with something a little more simple and
    elegant, like a 'Consumer', which represents an effectful sink of values.  A
    'Consumer' is a monad transformer that extends the base monad with a new
    'await' command. This 'await' command lets you receive input from an
    anonymous upstream source.

    The following @stdoutLn@ 'Consumer' shows how to incrementally 'await'
    'String's and print them to standard output, terminating gracefully when
    receiving a broken pipe error:

> import Control.Monad (unless)
> import Control.Exception (try, throwIO)
> import qualified GHC.IO.Exception as G
> import Pipes
>
> --          +--------+-- A 'Consumer' that awaits 'String's
> --          |        |
> --          v        v
> stdoutLn :: Consumer String IO ()
> stdoutLn = do
>     str <- await  -- 'await' a 'String'
>     x   <- lift $ try $ putStrLn str
>     case x of
>         -- Gracefully terminate if we got a broken pipe error
>         Left e@(G.IOError { G.ioe_type = t}) ->
>             lift $ unless (t == G.ResourceVanished) $ throwIO e
>         -- Otherwise loop
>         Right () -> stdoutLn

    'await' is the dual of 'yield': we suspend our 'Consumer' until we receive a
    new value.  If nobody provides a value (which is possible) then 'await'
    never returns.  You can think of 'await' as having the following type:

@
 'await' :: 'Monad' m => 'Consumer' a m a
@

    One way to feed a 'Consumer' is to repeatedly feed the same input using
    ('>~') (pronounced \"feed\"):

@
 \-\-                 +- Feed       +- Consumer to    +- Returns new
 \-\-                 |  action     |  feed           |  Effect
 \-\-                 v             v                 v  
 \-\-                 ----------    --------------    ----------
 ('>~') :: 'Monad' m => 'Effect' m b -> 'Consumer' b m c -> 'Effect' m c
@

    @(draw >~ consumer)@ loops over @(consumer)@, substituting each 'await' in
    @(consumer)@ with @(draw)@.

    So the following code replaces every 'await' in 'P.stdoutLn' with
    @(lift getLine)@ and then removes all the 'lift's:

>>> runEffect $ lift getLine >~ stdoutLn
Test<Enter>
Test
ABC<Enter>
ABC
42<Enter>
42
...

    You might wonder why ('>~') uses an 'Effect' instead of a raw action in the
    base monad.  The reason why is that ('>~') actually permits the following
    more general type:

@
 ('>~') :: 'Monad' m => 'Consumer' a m b -> 'Consumer' b m c -> 'Consumer' a m c
@

    ('>~') is the dual of ('~>'), composing 'Consumer's instead of 'Producer's.

    This means that you can feed a 'Consumer' with yet another 'Consumer' so
    that you can 'await' while you 'await'.  For example, we could define the
    following intermediate 'Consumer' that requests two 'String's and returns
    them concatenated:

> doubleUp :: Monad m => Consumer String m String
> doubleUp = do
>     str1 <- await
>     str2 <- await
>     return (str1 ++ str2)
>
> -- more concise: doubleUp = (++) <$> await <*> await

    We can now insert this in between @(lift getLine)@ and @stdoutLn@ and see
    what happens:

>>> runEffect $ lift getLine >~ doubleUp >~ stdoutLn
Test<Enter>
ing<Enter>
Testing
ABC<Enter>
DEF<Enter>
ABCDEF
42<Enter>
000<Enter>
42000
...

    'doubleUp' splits every request from 'stdoutLn' into two separate requests
    and
    returns back the concatenated result.

    We didn't need to parenthesize the above chain of ('>~') operators, because
    ('>~') is associative:

> -- Associativity
> (f >~ g) >~ h = f >~ (g >~ h)

    ... so we can always omit the parentheses since the meaning is unambiguous:

> f >~ g >~ h

    Also, ('>~') has an identity, which is 'await'!

> -- Left identity
> await >~ f = f
>
> -- Right Identity
> f >~ await = f

    In other words, ('>~') and 'await' form a 'Category', too, specifically the
    iteratee category, and 'Consumer's are also composable.
-}

{- $pipes
    Our previous programs were unsatisfactory because they were biased either
    towards the 'Producer' end or the 'Consumer' end.  As a result, we had to
    choose between gracefully handling end of input (using 'P.stdinLn') or
    gracefully handling end of output (using 'P.stdoutLn'), but not both at the
    same time.

    However, we don't need to restrict ourselves to using 'Producer's
    exclusively or 'Consumer's exclusively.  We can connect 'Producer's and
    'Consumer's directly together using ('>->') (pronounced \"pipe\"):

@
 ('>->') :: 'Monad' m => 'Producer' a m r -> 'Consumer' a m r -> 'Effect' m r
@

    This returns an 'Effect' which we can run:

> -- echo2.hs
>
> import Pipes
> import qualified Pipes.Prelude as P  -- Pipes.Prelude also provides 'stdoutLn'
>
> main = runEffect $ P.stdinLn >-> P.stdoutLn

    This program is more declarative of our intent: we want to stream values
    from 'P.stdinLn' to 'P.stdoutLn'.  The above \"pipeline\" not only echoes
    standard input to standard output, but also handles both end of input and
    broken pipe errors:

> $ ./echo2
> Test<Enter>
> Test
> ABC<Enter>
> ABC
> 42<Enter>
> 42
> <Ctrl-D>
> $

    ('>->') is \"pull-based\" meaning that control flow begins at the most
    downstream component (i.e. 'P.stdoutLn' in the above example).  Any time a
    component 'await's a value it blocks and transfers control upstream and
    every time a component 'yield's a value it blocks and restores control back
    downstream, satisfying the 'await'.  So in the above example, ('>->')
    matches every 'await' from 'P.stdoutLn' with a 'yield' from 'P.stdinLn'.

    Streaming stops when either 'P.stdinLn' terminates (i.e. end of input) or
    'P.stdoutLn' terminates (i.e. broken pipe).  This is why ('>->') requires
    that both the 'Producer' and 'Consumer' share the same type of return value:
    whichever one terminates first provides the return value for the entire
    'Effect'.

    Let's test this by modifying our 'Producer' and 'Consumer' to each return a
    diagnostic 'String':

> -- echo3.hs
>
> import Control.Applicative ((<$))  -- (<$) modifies return values
> import Pipes
> import qualified Pipes.Prelude as P
> import System.IO
>
> main = do
>     hSetBuffering stdout NoBuffering
>     str <- runEffect $
>         ("End of input!" <$ P.stdinLn) >-> ("Broken pipe!" <$ P.stdoutLn)
>     hPutStrLn stderr str

    This lets us diagnose whether the 'Producer' or 'Consumer' terminated first:

> $ ./echo3
> Test<Enter>
> Test
> <Ctrl-D>
> End of input!
> $ ./echo3 | perl -e 'close STDIN'
> Test<Enter>
> Broken pipe!
> $

    You might wonder why ('>->') returns an 'Effect' that we have to run instead
    of directly returning an action in the base monad.  This is because you can
    connect things other than 'Producer's and 'Consumer's, like 'Pipe's, which
    are effectful stream transformations.

    A 'Pipe' is a monad transformer that is a mix between a 'Producer' and
    'Consumer', because a 'Pipe' can both 'await' and 'yield'.  The following
    example 'Pipe' is analogous to the Prelude's 'take', only allowing a fixed
    number of values to flow through:

> -- take.hs
>
> import Control.Monad (replicateM_)
> import Pipes
> import Prelude hiding (take)
>
> --              +--------- A 'Pipe' that
> --              |    +---- 'await's 'a's and
> --              |    | +-- 'yield's 'a's
> --              |    | |
> --              v    v v
> take ::  Int -> Pipe a a IO ()
> take n = do
>     replicateM_ n $ do                     -- Repeat this block 'n' times
>         x <- await                         -- 'await' a value of type 'a'
>         yield x                            -- 'yield' a value of type 'a'
>     lift $ putStrLn "You shall not pass!"  -- Fly, you fools!

    You can use 'Pipe's to transform 'Producer's, 'Consumer's, or even other
    'Pipe's using the same ('>->') operator:

@
 ('>->') :: 'Monad' m => 'Producer' a m r -> 'Pipe'   a b m r -> 'Producer' b m r
 ('>->') :: 'Monad' m => 'Pipe'   a b m r -> 'Consumer' b m r -> 'Consumer' a m r
 ('>->') :: 'Monad' m => 'Pipe'   a b m r -> 'Pipe'   b c m r -> 'Pipe'   a c m r
@

    For example, you can compose 'P.take' after 'P.stdinLn' to limit the number
    of lines drawn from standard input:

> maxInput :: Int -> Producer String IO ()
> maxInput n = P.stdinLn >-> take n

>>> runEffect $ maxInput 3 >-> P.stdoutLn
Test<Enter>
Test
ABC<Enter>
ABC
42<Enter>
42
You shall not pass!
>>>

    ... or you can pre-compose 'P.take' before 'P.stdoutLn' to limit the number
    of lines written to standard output:

> maxOutput :: Int -> Consumer String IO ()
> maxOutput n = take n >-> P.stdoutLn

>>> runEffect $ P.stdinLn >-> maxOutput 3
<Exact same behavior>

    Those both gave the same behavior because ('>->') is associative:

> (p1 >-> p2) >-> p3 = p1 >-> (p2 >-> p3)

    Therefore we can just leave out the parentheses:

>>> runEffect $ P.stdinLn >-> take 3 >-> P.stdoutLn
<Exact same behavior>

    ('>->') is designed to behave like the Unix pipe operator, except with less
    quirks.  In fact, we can continue the analogy to Unix by defining 'cat'
    (named after the Unix @cat@ utility), which reforwards elements endlessly:

> cat :: Monad m => Pipe a a m r
> cat = forever $ do
>     x <- await
>     yield x

     'cat' is the identity of ('>->'), meaning that 'cat' satisfies the
     following two laws:

> -- Useless use of 'cat'
> cat >-> p = p
>
> -- Forwarding output to 'cat' does nothing
> p >-> cat = p

    Therefore, ('>->') and 'cat' form a 'Category', specifically the category of
    Unix pipes, and 'Pipe's are also composable.

    A lot of Unix tools have very simple definitions when written using @pipes@:

> -- unix.hs
>
> import Control.Monad (forever)
> import Pipes
> import qualified Pipes.Prelude as P  -- Pipes.Prelude provides 'take', too
> import Prelude hiding (head)
>
> head :: Monad m => Int -> Pipe a a m ()
> head = P.take
>
> yes :: Monad m => Producer String m r
> yes = forever $ yield "y"
>
> main = runEffect $ yes >-> head 3 >-> P.stdoutLn

    This prints out 3 \'@y@\'s, just like the equivalent Unix pipeline:

> $ ./unix
> y
> y
> y
> $ yes | head -3
> y
> y
> y
> $

    This lets us write \"Haskell pipes\" instead of Unix pipes.  These are much
    easier to build than Unix pipes and we can connect them directly within
    Haskell for interoperability with the Haskell language and ecosystem.
-}

{- $listT
    @pipes@ also provides a \"ListT done right\" implementation.  This differs
    from the implementation in @transformers@ because this 'ListT':

    * obeys the monad laws, and

    * streams data immediately instead of collecting all results into memory.

    The latter property is actually an elegant consequence of obeying the monad
    laws.

    To bind a list within a 'ListT' computation, combine 'Select' and 'each':

> import Pipes
> 
> pair :: ListT IO (Int, Int)
> pair = do
>     x <- Select $ each [1, 2]
>     lift $ putStrLn $ "x = " ++ show x
>     y <- Select $ each [3, 4]
>     lift $ putStrLn $ "y = " ++ show y
>     return (x, y)

    You can then loop over a 'ListT' by using 'every':

@
 'every' :: 'Monad' m => 'ListT' m a -> 'Producer' a m ()
@

    So you can use your 'ListT' within a 'for' loop:

>>> runEffect $ for (every pair) (lift . print)
x = 1
y = 3
(1,3)
y = 4
(1,4)
x = 2
y = 3
(2,3)
y = 4
(2,4)

    ... or a pipeline:

>>> import qualified Pipes.Prelude as P
>>> runEffect $ every pair >-> P.print
<Exact same behavior>

    Note that 'ListT' is lazy and only produces as many elements as we request:

>>> runEffect $ for (every pair >-> P.take 2) (lift . print)
x = 1
y = 3
(1,3)
y = 4
(1,4)

    You can also go the other way, binding 'Producer's directly within a
    'ListT'.  In fact, this is actually what 'Select' was already doing:

@
 'Select' :: 'Producer' a m () -> 'ListT' m a
@

    This lets you write crazy code like:

> import Pipes
> import qualified Pipes.Prelude as P
> 
> input :: Producer String IO ()
> input = P.stdinLn >-> P.takeWhile (/= "quit")
> 
> name :: ListT IO String
> name = do
>     firstName <- Select input
>     lastName  <- Select input
>     return (firstName ++ " " ++ lastName)

    Here we're binding standard input non-deterministically (twice) as if it
    were an effectful list:

>>> runEffect $ every name >-> P.stdoutLn
Daniel<Enter>
Fischer<Enter>
Daniel Fischer
Wagner<Enter>
Daniel Wagner
quit<Enter>
Donald<Enter>
Stewart<Enter>
Donald Stewart
Duck<Enter>
Donald Duck
quit<Enter>
quit<Enter>
>>>

    Notice how this streams out values immediately as they are generated, rather
    than building up a large intermediate result and then printing all the
    values in one batch at the end.

    `ListT` computations can be combined in more ways than `Pipe`s, so try to
    program in `ListT` as much as possible and defer converting it to a `Pipe`
    as late as possible using `P.loop`.

    You can combine `ListT` computations even if their inputs and outputs are
    completely different:

> data In
>     = InA A
>     | InB B
>     | InC C
>
> data Out
>     = OutD D
>     | OutE E
>     | OutF F
>
> -- Independent computations
>
> example1 :: A -> ListT IO D
> example2 :: B -> ListT IO E
> example3 :: C -> ListT IO F
>
> -- Combined computation
>
> total :: In -> ListT IO Out
> total input = case input of
>     InA a -> fmap OutD (example1 a)
>     InB b -> fmap OutE (example2 b)
>     InC c -> fmap OutF (example3 c)

    Sometimes you have multiple computations that handle different inputs but
    the same output, in which case you don't need to unify their outputs:

> -- Overlapping outputs
>
> example1 :: A -> ListT IO Out
> example2 :: B -> ListT IO Out
> example3 :: C -> ListT IO Out
>
> -- Combined computation
>
> total :: In -> ListT IO Out
> total input = case input of
>     InA a -> example1 a
>     InB b -> example2 b
>     InC c -> example3 c

    Other times you have multiple computations that handle the same input but
    produce different outputs.  You can unify their outputs using the `Monoid`
    and `Functor` instances for `ListT`:

> -- Overlapping inputs
>
> example1 :: In -> ListT IO D
> example2 :: In -> ListT IO E
> example3 :: In -> ListT IO F
>
> -- Combined computation
>
> total :: In -> ListT IO Out
> total input =
>        fmap OutD (example1 input)
>     <> fmap OutE (example2 input)
>     <> fmap OutF (example3 input)

    You can also chain `ListT` computations, feeding the output of the first
    computation as the input to the next computation:

> -- End-to-end
>
> aToB :: A -> ListT IO B
> bToC :: B -> ListT IO C
>
> -- Combined computation
>
> aToC :: A -> LIstT IO C
> aToC = aToB >=> bToC

    ... or you can just use @do@ notation if you prefer.

    However, the `Pipe` type is more general than `ListT` and can represent
    things like termination.  Therefore you should consider mixing `Pipe`s with
    `ListT` when you need to take advantage of these extra features:

> -- Mix ListT with Pipes
>
> example :: In -> ListT IO Out
>
> pipe :: Pipe In Out IO ()
> pipe = Pipes.takeWhile (not . isC) >-> loop example
>   where
>     isC (InC _) = True
>     isC  _      = False

    So promote your `ListT` logic to a `Pipe` when you need to take advantage of
    these `Pipe`-specific features.
-}

{- $tricks
    @pipes@ is more powerful than meets the eye so this section presents some
    non-obvious tricks you may find useful.

    Many pipe combinators will work on unusual pipe types and the next few
    examples will use the 'cat' pipe to demonstrate this.

    For example, you can loop over the output of a 'Pipe' using 'for', which is
    how 'P.map' is defined:

> map :: Monad m => (a -> b) -> Pipe a b m r
> map f = for cat $ \x -> yield (f x)
>
> -- Read this as: For all values flowing downstream, apply 'f'

    This is equivalent to:

> map f = forever $ do
>     x <- await
>     yield (f x)

    You can also feed a 'Pipe' input using ('>~').  This means we could have
    instead defined the @yes@ pipe like this:

> yes :: Monad m => Producer String m r
> yes = return "y" >~ cat
>
> -- Read this as: Keep feeding "y" downstream

    This is equivalent to:

> yes = forever $ yield "y"

    You can also sequence two 'Pipe's together.  This is how 'P.drop' is
    defined:

> drop :: Monad m => Int -> Pipe a a m r
> drop n = do
>     replicateM_ n await
>     cat

    This is equivalent to:

> drop n = do
>     replicateM_ n await
>     forever $ do
>         x <- await
>         yield x

    You can even compose pipes inside of another pipe:

> customerService :: Producer String IO ()
> customerService = do
>     each [ "Hello, how can I help you?"        -- Begin with a script
>          , "Hold for one second."
>          ]
>     P.stdinLn >-> P.takeWhile (/= "Goodbye!")  -- Now continue with a human

    Also, you can often use 'each' in conjunction with ('~>') to traverse nested
    data structures.  For example, you can print all non-'Nothing' elements
    from a doubly-nested list:

>>> runEffect $ (each ~> each ~> each ~> lift . print) [[Just 1, Nothing], [Just 2, Just 3]]
1
2
3

    Another neat thing to know is that 'every' has a more general type:

@
 'every' :: ('Monad' m, 'Enumerable' t) => t m a -> 'Producer' a m ()
@

    'Enumerable' generalizes 'Foldable' and if you have an effectful container
    of your own that you want others to traverse using @pipes@, just have your
    container implement the 'toListT' method of the 'Enumerable' class:

> class Enumerable t where
>     toListT :: Monad m => t m a -> ListT m a

    You can even use 'Enumerable' to traverse effectful types that are not even
    proper containers, like 'Control.Monad.Trans.Maybe.MaybeT':

> input :: MaybeT IO String
> input = do
>     str <- lift getLine
>     guard (str /= "Fail")
>     return str

>>> runEffect $ every input >-> P.stdoutLn
Test<Enter>
Test
>>> runEffect $ every input >-> P.stdoutLn
Fail<Enter>
>>>

-}

{- $conclusion
    This tutorial covers the concepts of connecting, building, and reading
    @pipes@ code.  However, this library is only the core component in an
    ecosystem of streaming components.  Derived libraries that build immediately
    upon @pipes@ include:

    * @pipes-concurrency@: Concurrent reactive programming and message passing

    * @pipes-parse@: Minimal utilities for stream parsing

    * @pipes-safe@: Resource management and exception safety for @pipes@

    * @pipes-group@: Grouping streams in constant space

    These libraries provide functionality specialized to common streaming
    domains.  Additionally, there are several libraries on Hackage that provide
    even higher-level functionality, which you can find by searching under the
    \"Pipes\" category or by looking for packages with a @pipes-@ prefix in
    their name.  Current examples include:

    * @pipes-extras@: Miscellaneous utilities

    * @pipes-network@/@pipes-network-tls@: Networking

    * @pipes-zlib@: Compression and decompression

    * @pipes-binary@: Binary serialization

    * @pipes-attoparsec@: High-performance parsing

    * @pipes-aeson@: JSON serialization and deserialization

    Even these derived packages still do not explore the full potential of
    @pipes@ functionality, which actually permits bidirectional communication.
    Advanced @pipes@ users can explore this library in greater detail by
    studying the documentation in the "Pipes.Core" module to learn about the
    symmetry of the underlying 'Proxy' type and operators.

    To learn more about @pipes@, ask questions, or follow @pipes@ development,
    you can subscribe to the @haskell-pipes@ mailing list at:

    <https://groups.google.com/forum/#!forum/haskell-pipes>

    ... or you can mail the list directly at:

    <mailto:haskell-pipes@googlegroups.com>

    Additionally, for questions regarding types or type errors, you might find
    the following appendix on types very useful.
-}

{- $types
    @pipes@ uses parametric polymorphism (i.e. generics) to overload all
    operations.  You've probably noticed this overloading already:

    * 'yield' works within both 'Producer's and 'Pipe's

    * 'await' works within both 'Consumer's and 'Pipe's

    * ('>->') connects 'Producer's, 'Consumer's, and 'Pipe's in varying ways

    This overloading is great when it works, but when connections fail they
    produce type errors that appear intimidating at first.  This section
    explains the underlying types so that you can work through type errors
    intelligently.

    'Producer's, 'Consumer's, 'Pipe's, and 'Effect's are all special cases of a
    single underlying type: a 'Proxy'.  This overarching type permits fully
    bidirectional communication on both an upstream and downstream interface.
    You can think of it as having the following shape:

> Proxy a' a b' b m r
>
> Upstream | Downstream
>     +---------+
>     |         |
> a' <==       <== b'  -- Information flowing upstream
>     |         |
> a  ==>       ==> b   -- Information flowing downstream
>     |    |    |
>     +----|----+
>          v
>          r

    The four core types do not use the upstream flow of information.  This means
    that the @a'@ and @b'@ in the above diagram go unused unless you use the
    more advanced features provided in "Pipes.Core".

    @pipes@ uses type synonyms to hide unused inputs or outputs and clean up
    type signatures.  These type synonyms come in two flavors:

    * Concrete type synonyms that explicitly close unused inputs and outputs of
      the 'Proxy' type

    * Polymorphic type synonyms that don't explicitly close unused inputs or
      outputs

    The concrete type synonyms use @()@ to close unused inputs and 'X' (the
    uninhabited type) to close unused outputs:

    * 'Effect': explicitly closes both ends, forbidding 'await's and 'yield's

> type Effect = Proxy X () () X
>
>  Upstream | Downstream
>     +---------+
>     |         |
> X  <==       <== ()
>     |         |
> () ==>       ==> X
>     |    |    |
>     +----|----+
>          v
>          r

    * 'Producer': explicitly closes the upstream end, forbidding 'await's

> type Producer b = Proxy X () () b
>
> Upstream | Downstream
>     +---------+
>     |         |
> X  <==       <== ()
>     |         |
> () ==>       ==> b
>     |    |    |
>     +----|----+
>          v
>          r

    * 'Consumer': explicitly closes the downstream end, forbidding 'yield's
Download .txt
gitextract_l6xj46in/

├── .github/
│   └── workflows/
│       └── haskell.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── Setup.hs
├── benchmarks/
│   ├── Common.hs
│   ├── LiftBench.hs
│   └── PreludeBench.hs
├── laws.md
├── nix/
│   └── .gitkeep
├── pipes.cabal
├── release.nix
├── shell.nix
├── src/
│   ├── Pipes/
│   │   ├── Core.hs
│   │   ├── Internal.hs
│   │   ├── Lift.hs
│   │   ├── Prelude.hs
│   │   └── Tutorial.hs
│   └── Pipes.hs
├── stack.yaml
└── tests/
    └── Main.hs
Condensed preview — 22 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (249K chars).
[
  {
    "path": ".github/workflows/haskell.yml",
    "chars": 883,
    "preview": "name: Haskell CI\n\non:\n  push:\n    branches: [ main ]\n  pull_request:\n    branches: [ main ]\n\njobs:\n  build:\n\n    runs-on"
  },
  {
    "path": ".gitignore",
    "chars": 63,
    "preview": "cabal-dev\n.cabal-sandbox\ncabal.sandbox.config\ndist\n.stack-work\n"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 3356,
    "preview": "4.3.16\n\n* Fix example code for `every`\n* Improved documentation for `ListT`\n\n4.3.15\n\n* Build against `ghc-9.0`\n\n4.3.14\n\n"
  },
  {
    "path": "LICENSE",
    "chars": 1528,
    "preview": "Copyright (c) 2012-2016 Gabriella Gonzalez\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with"
  },
  {
    "path": "README.md",
    "chars": 4592,
    "preview": "# `pipes`\n\n`pipes` is a clean and powerful stream processing library that lets you build\nand connect reusable streaming "
  },
  {
    "path": "Setup.hs",
    "chars": 46,
    "preview": "import Distribution.Simple\nmain = defaultMain\n"
  },
  {
    "path": "benchmarks/Common.hs",
    "chars": 777,
    "preview": "module Common (commonMain) where\n\nimport Criterion.Main (Benchmark, runMode)\nimport Criterion.Main.Options as Criterion\n"
  },
  {
    "path": "benchmarks/LiftBench.hs",
    "chars": 1990,
    "preview": "{-# LANGUAGE RankNTypes #-}\nmodule Main (main) where\n\nimport Common (commonMain)\nimport Control.Monad.Identity\nimport qu"
  },
  {
    "path": "benchmarks/PreludeBench.hs",
    "chars": 3220,
    "preview": "{-# LANGUAGE RankNTypes #-}\nmodule Main (main) where\n\nimport Criterion.Main\nimport Common (commonMain)\nimport Control.Mo"
  },
  {
    "path": "laws.md",
    "chars": 68393,
    "preview": "# Kleisli Category\n\n    Define:\n    \n    return\n        :: (Monad m)\n        =>  r -> Proxy a' a b' b m r\n    return = P"
  },
  {
    "path": "nix/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "pipes.cabal",
    "chars": 3753,
    "preview": "Name: pipes\nVersion: 4.3.16\nCabal-Version: >= 1.10\nBuild-Type: Simple\nTested-With: GHC == 7.10.3, GHC == 8.0.2, GHC == 8"
  },
  {
    "path": "release.nix",
    "chars": 844,
    "preview": "let\n  overlay = pkgsNew: pkgsOld: {\n    haskellPackages = pkgsOld.haskellPackages.override (old: {\n      overrides =\n   "
  },
  {
    "path": "shell.nix",
    "chars": 33,
    "preview": "(import ./release.nix).pipes.env\n"
  },
  {
    "path": "src/Pipes/Core.hs",
    "chars": 22987,
    "preview": "{-| The core functionality for the 'Proxy' monad transformer\n\n    Read \"Pipes.Tutorial\" if you want a beginners tutorial"
  },
  {
    "path": "src/Pipes/Internal.hs",
    "chars": 9538,
    "preview": "{-| This is an internal module, meaning that it is unsafe to import unless you\n    understand the risks.\n\n    This modul"
  },
  {
    "path": "src/Pipes/Lift.hs",
    "chars": 10168,
    "preview": "{-# LANGUAGE CPP #-}\n\n{-| Many actions in base monad transformers cannot be automatically\n    'Control.Monad.Trans.Class"
  },
  {
    "path": "src/Pipes/Prelude.hs",
    "chars": 24938,
    "preview": "{-| General purpose utilities\n\n    The names in this module clash heavily with the Haskell Prelude, so I\n    recommend t"
  },
  {
    "path": "src/Pipes/Tutorial.hs",
    "chars": 51249,
    "preview": "{-# OPTIONS_GHC -fno-warn-unused-imports #-}\n\n{-| Conventional Haskell stream programming forces you to choose only two "
  },
  {
    "path": "src/Pipes.hs",
    "chars": 21819,
    "preview": "{-# LANGUAGE CPP                   #-}\n{-# LANGUAGE RankNTypes            #-}\n{-# LANGUAGE FlexibleInstances     #-}\n{-#"
  },
  {
    "path": "stack.yaml",
    "chars": 19,
    "preview": "resolver: lts-6.13\n"
  },
  {
    "path": "tests/Main.hs",
    "chars": 7653,
    "preview": "module Main (main) where\n\nimport Data.Function                        (on)\nimport Data.List                            ("
  }
]

About this extraction

This page contains the full source code of the Gabriel439/Haskell-Pipes-Library GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 22 files (232.3 KB), approximately 67.4k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!