Pipes

pipes-4.1.8: Compositional pipelines

Safe Haskell | Trustworthy
Language | Haskell2010

Pipes

Contents

- The Proxy Monad Transformer
  - Producers
  - Consumers
  - Pipes
- ListT
- Utilities
- Re-exports

Description

This module is the recommended entry point to the `pipes` library.

Read Pipes.Tutorial if you want a tutorial explaining how to use this library.

Synopsis

- data Proxy a' a b' b m r
- data X
- type Effect = Proxy X () () X
- type Effect' m r = forall x' x y' y. Proxy x' x y' y m r
- runEffect :: Monad m => Effect m r -> m r
- type Producer b = Proxy X () () b
- type Producer' b m r = forall x' x. Proxy x' x () b m r
- yield :: Monad m => a -> Producer' a m ()
- for :: Monad m => Proxy x' x b' b m a' -> (b -> Proxy x' x c' c m b') -> Proxy x' x c' c m a'
- (~>) :: 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'
- (<~) :: Monad 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'
- type Consumer a = Proxy () a () X
- type Consumer' a m r = forall y' y. Proxy () a y' y m r
- await :: Monad m => Consumer' a m a
- (>~) :: Monad m => Proxy a' a y' y m b -> Proxy () b y' y m c -> Proxy a' a y' y m c
- (~<) :: Monad m => Proxy () b y' y m c -> Proxy a' a y' y m b -> Proxy a' a y' y m c
- type Pipe a b = Proxy () a () b
- cat :: Monad m => Pipe a a m r
- (>->) :: Monad m => Proxy a' a () b m r -> Proxy () b c' c m r -> Proxy a' a c' c m r
- (<-<) :: Monad m => Proxy () b c' c m r -> Proxy a' a () b m r -> Proxy a' a c' c m r
- newtype ListT m a = Select {
  - enumerate :: Producer a m ()
  }
- runListT :: Monad m => ListT m a -> m ()
- class Enumerable t where
  - toListT :: Monad m => t m a -> ListT m a
- next :: Monad m => Producer a m r -> m (Either r (a, Producer a m r))
- each :: (Monad m, Foldable f) => f a -> Producer' a m ()
- every :: (Monad m, Enumerable t) => t m a -> Producer' a m ()
- discard :: Monad m => a -> m ()
- module Control.Monad
- module Control.Monad.IO.Class
- module Control.Monad.Trans.Class
- module Control.Monad.Morph
- module Data.Foldable

# The Proxy Monad Transformer

data Proxy a' a b' b m r

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

Instances

MonadError e m => MonadError e (Proxy a' a b' b m) |
MonadReader r m => MonadReader r (Proxy a' a b' b m) |
MonadState s m => MonadState s (Proxy a' a b' b m) |
MonadWriter w m => MonadWriter w (Proxy a' a b' b m) |
MFunctor (Proxy a' a b' b) |
MMonad (Proxy a' a b' b) |
MonadTrans (Proxy a' a b' b) |
Monad m => Monad (Proxy a' a b' b m) |
Monad m => Functor (Proxy a' a b' b m) |
Monad m => Applicative (Proxy a' a b' b m) |
MonadPlus m => Alternative (Proxy a' a b' b m) |
MonadPlus m => MonadPlus (Proxy a' a b' b m) |
MonadIO m => MonadIO (Proxy a' a b' b m) |
(Monad m, Monoid r) => Monoid (Proxy a' a b' b m r) |

data X

The empty type, used to close output ends

When `Data.Void` is merged into `base`, this will change to:

    type X = Void

type Effect = Proxy X () () X

An effect in the base monad

`Effect`s neither `await` nor `yield`

type Effect' m r = forall x' x y' y. Proxy x' x y' y m r

Like `Effect`, but with a polymorphic type

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

Run a self-contained `Effect`, converting it back to the base monad

## Producers

Use `yield` to produce output and (`~>`) / `for` to substitute `yield`s.

`yield` and (`~>`) obey the `Category` laws:

    -- Substituting 'yield' with 'f' gives 'f'
    yield ~> f = f

    -- Substituting every 'yield' with another 'yield' does nothing
    f ~> yield = f

    -- 'yield' substitution is associative
    (f ~> g) ~> h = f ~> (g ~> h)

These are equivalent to the following "for loop laws":

    -- Looping over a single yield simplifies to function application
    for (yield x) f = f x

    -- Re-yielding every element of a stream returns the original stream
    for s yield = s

    -- Nested for loops can become a sequential for loops if the inner loop
    -- body ignores the outer loop variable
    for s (\a -> for (f a) g) = for (for s f) g = for s (f ~> g)

type Producer b = Proxy X () () b

`Producer`s can only `yield`

type Producer' b m r = forall x' x. Proxy x' x () b m r

Like `Producer`, but with a polymorphic type

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

Produce a value

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

for

Arguments

:: Monad m |
=> Proxy x' x b' b m a' |
-> (b -> Proxy x' x c' c m b') |
-> Proxy x' x c' c m a' |

`(for p body)` loops over `p` replacing each `yield` with `body`.

    for :: Monad m => Producer b m r -> (b -> Effect       m ()) -> Effect       m r
    for :: Monad m => Producer b m r -> (b -> Producer   c m ()) -> Producer   c m r
    for :: Monad m => Pipe   x b m r -> (b -> Consumer x   m ()) -> Consumer x   m r
    for :: Monad m => Pipe   x b m r -> (b -> Pipe     x c m ()) -> Pipe     x c m r

The following diagrams show the flow of information:

                                  .--->   b
                                 /        |
       +-----------+            /   +-----|-----+                 +---------------+
       |           |           /    |     v     |                 |               |
       |           |          /     |           |                 |               |
    x ==>    p    ==> b   ---'   x ==>   body  ==> c     =     x ==> for p body  ==> c
       |           |                |           |                 |               |
       |     |     |                |     |     |                 |       |       |
       +-----|-----+                +-----|-----+                 +-------|-------+
             v                            v                               v
             r                            ()                              r

For a more complete diagram including bidirectional flow, see Pipes.Core.

(~>) infixr 4

Arguments

:: 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' |

Compose loop bodies

    (~>) :: Monad m => (a -> Producer b m r) -> (b -> Effect       m ()) -> (a -> Effect       m r)
    (~>) :: Monad m => (a -> Producer b m r) -> (b -> Producer   c m ()) -> (a -> Producer   c m r)
    (~>) :: Monad m => (a -> Pipe   x b m r) -> (b -> Consumer x   m ()) -> (a -> Consumer x   m r)
    (~>) :: Monad m => (a -> Pipe   x b m r) -> (b -> Pipe     x c m ()) -> (a -> Pipe     x c m r)

The following diagrams show the flow of information:

             a                    .--->   b                              a
             |                   /        |                              |
       +-----|-----+            /   +-----|-----+                 +------|------+
       |     v     |           /    |     v     |                 |      v      |
       |           |          /     |           |                 |             |
    x ==>    f    ==> b   ---'   x ==>    g    ==> c     =     x ==>   f ~> g  ==> c
       |           |                |           |                 |             |
       |     |     |                |     |     |                 |      |      |
       +-----|-----+                +-----|-----+                 +------|------+
             v                            v                              v
             r                            ()                             r

For a more complete diagram including bidirectional flow, see Pipes.Core.

(<~) infixl 4

Arguments

:: Monad 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' |

(`~>`) with the arguments flipped

## Consumers

Use `await` to request input and (`>~`) to substitute `await`s.

`await` and (`>~`) obey the `Category` laws:

    -- Substituting every 'await' with another 'await' does nothing
    await >~ f = f

    -- Substituting 'await' with 'f' gives 'f'
    f >~ await = f

    -- 'await' substitution is associative
    (f >~ g) >~ h = f >~ (g >~ h)

type Consumer a = Proxy () a () X

`Consumer`s can only `await`

type Consumer' a m r = forall y' y. Proxy () a y' y m r

Like `Consumer`, but with a polymorphic type

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

Consume a value

    await :: Monad m => Pipe a y m a

(>~) infixr 5

Arguments

:: Monad m |
=> Proxy a' a y' y m b |
-> Proxy () b y' y m c |
-> Proxy a' a y' y m c |

`(draw >~ p)` loops over `p` replacing each `await` with `draw`

    (>~) :: Monad m => Effect       m b -> Consumer b   m c -> Effect       m c
    (>~) :: Monad m => Consumer a   m b -> Consumer b   m c -> Consumer a   m c
    (>~) :: Monad m => Producer   y m b -> Pipe     b y m c -> Producer   y m c
    (>~) :: Monad m => Pipe     a y m b -> Pipe     b y m c -> Pipe     a y m c

The following diagrams show the flow of information:

       +-----------+                 +-----------+                 +-------------+
       |           |                 |           |                 |             |
       |           |                 |           |                 |             |
    a ==>    f    ==> y   .--->   b ==>    g    ==> y     =     a ==>   f >~ g  ==> y
       |           |     /           |           |                 |             |
       |     |     |    /            |     |     |                 |      |      |
       +-----|-----+   /             +-----|-----+                 +------|------+
             v        /                    v                              v
             b   ----'                     c                              c

For a more complete diagram including bidirectional flow, see Pipes.Core.

(~<) infixl 5

Arguments

:: Monad m |
=> Proxy () b y' y m c |
-> Proxy a' a y' y m b |
-> Proxy a' a y' y m c |

(`>~`) with the arguments flipped

## Pipes

Use `await` and `yield` to build `Pipe`s and (`>->`) to connect `Pipe`s.

`cat` and (`>->`) obey the `Category` laws:

    -- Useless use of cat
    cat >-> f = f

    -- Redirecting output to cat does nothing
    f >-> cat = f

    -- The pipe operator is associative
    (f >-> g) >-> h = f >-> (g >-> h)

type Pipe a b = Proxy () a () b

`Pipe`s can both `await` and `yield`

cat :: Monad m => Pipe a a m r

The identity `Pipe`, analogous to the Unix `cat` program

(>->) infixl 7

Arguments

:: Monad m |
=> Proxy a' a () b m r |
-> Proxy () b c' c m r |
-> Proxy a' a c' c m r |

`Pipe` composition, analogous to the Unix pipe operator

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

The following diagrams show the flow of information:

       +-----------+     +-----------+                 +-------------+
       |           |     |           |                 |             |
       |           |     |           |                 |             |
    a ==>    f    ==> b ==>    g    ==> c     =     a ==>  f >-> g  ==> c
       |           |     |           |                 |             |
       |     |     |     |     |     |                 |      |      |
       +-----|-----+     +-----|-----+                 +------|------+
             v                 v                              v
             r                 r                              r

For a more complete diagram including bidirectional flow, see Pipes.Core.

(<-<) infixr 7

Arguments

:: Monad m |
=> Proxy () b c' c m r |
-> Proxy a' a () b m r |
-> Proxy a' a c' c m r |

(`>->`) with the arguments flipped

# ListT

newtype ListT m a

The list monad transformer, which extends a monad with non-determinism

`return` corresponds to `yield`, yielding a single value

(`>>=`) corresponds to `for`, calling the second computation once for each time the first computation `yield`s.

Constructors

Select |
Fields enumerate :: Producer a m ()

Instances

MFunctor ListT |
MonadTrans ListT |
Enumerable ListT |
MonadError e m => MonadError e (ListT m) |
MonadReader i m => MonadReader i (ListT m) |
MonadState s m => MonadState s (ListT m) |
MonadWriter w m => MonadWriter w (ListT m) |
Monad m => Monad (ListT m) |
Monad m => Functor (ListT m) |
Monad m => Applicative (ListT m) |
Monad m => Alternative (ListT m) |
Monad m => MonadPlus (ListT m) |
MonadIO m => MonadIO (ListT m) |
Monad m => Monoid (ListT m a) |

runListT :: Monad m => ListT m a -> m ()

Run a self-contained `ListT` computation

class Enumerable t where

`Enumerable` generalizes `Foldable`, converting effectful containers to `ListT`s.

Instances of `Enumerable` must satisfy these two laws:

    toListT (return r) = return r

    toListT $ do x <- m  =  do x <- toListT m
                 f x           toListT (f x)

In other words, `toListT` is monad morphism.

Methods

toListT :: Monad m => t m a -> ListT m a

Instances

Enumerable MaybeT |
Enumerable IdentityT |
Enumerable ListT |
Enumerable (ErrorT e) |

# Utilities

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

Consume the first value from a `Producer`

`next` either fails with a `Left` if the `Producer` terminates or succeeds with a `Right` providing the next value and the remainder of the `Producer`.

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

Convert a `Foldable` to a `Producer`

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

Convert an `Enumerable` to a `Producer`

discard :: Monad m => a -> m ()

Discards a value

# Re-exports

Control.Monad re-exports `void`

Control.Monad.IO.Class re-exports `MonadIO`.

Control.Monad.Trans.Class re-exports `MonadTrans`.

Control.Monad.Morph re-exports `MFunctor`.

Data.Foldable re-exports `Foldable` (the class name only).

module Control.Monad

module Control.Monad.IO.Class

module Control.Monad.Trans.Class

module Control.Monad.Morph

module Data.Foldable