Safe Haskell | Trustworthy |
---|---|

Language | Haskell2010 |

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.

- data Proxy a' a b' b m r
- type X = Void
- 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 {}
- runListT :: Monad m => ListT m a -> m ()
- class Enumerable t where
- 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
- class Foldable t

# The Proxy Monad Transformer

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

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) # | |

MonadIO m => MonadIO (Proxy a' a b' b m) # | |

MonadThrow m => MonadThrow (Proxy a' a b' b m) # | |

MonadCatch m => MonadCatch (Proxy a' a b' b m) # | |

(Monad m, Semigroup r) => Semigroup (Proxy a' a b' b m r) # | |

(Monad m, Monoid r, Semigroup r) => Monoid (Proxy a' a b' b m r) # | |

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)

`(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.

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

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

`(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.

(`>~`

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

`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.

(`>->`

) with the arguments flipped

# ListT

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.

MFunctor ListT # | |

MMonad 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) # | |

Foldable m => Foldable (ListT m) # | |

(Monad m, Traversable m) => Traversable (ListT m) # | |

Monad m => MonadZip (ListT m) # | |

MonadIO m => MonadIO (ListT m) # | |

Monad m => Alternative (ListT m) # | |

Monad m => MonadPlus (ListT m) # | |

MonadThrow m => MonadThrow (ListT m) # | |

MonadCatch m => MonadCatch (ListT m) # | |

Monad m => Semigroup (ListT m a) # | |

Monad m => Monoid (ListT m a) # | |

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.

Enumerable MaybeT # | |

Enumerable ListT # | |

Enumerable (ExceptT e) # | |

Enumerable (IdentityT *) # | |

# Utilities

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

Convert an `Enumerable`

to a `Producer`

# 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

Data structures that can be folded.

For example, given a data type

data Tree a = Empty | Leaf a | Node (Tree a) a (Tree a)

a suitable instance would be

instance Foldable Tree where foldMap f Empty = mempty foldMap f (Leaf x) = f x foldMap f (Node l k r) = foldMap f l `mappend` f k `mappend` foldMap f r

This is suitable even for abstract types, as the monoid is assumed
to satisfy the monoid laws. Alternatively, one could define `foldr`

:

instance Foldable Tree where foldr f z Empty = z foldr f z (Leaf x) = f x z foldr f z (Node l k r) = foldr f (f k (foldr f z r)) l

`Foldable`

instances are expected to satisfy the following laws:

foldr f z t = appEndo (foldMap (Endo . f) t ) z

foldl f z t = appEndo (getDual (foldMap (Dual . Endo . flip f) t)) z

fold = foldMap id

`sum`

, `product`

, `maximum`

, and `minimum`

should all be essentially
equivalent to `foldMap`

forms, such as

sum = getSum . foldMap Sum

but may be less defined.

If the type is also a `Functor`

instance, it should satisfy

foldMap f = fold . fmap f

which implies that

foldMap f . fmap g = foldMap (f . g)