pipes-4.3.1: Compositional pipelines

Safe HaskellTrustworthy
LanguageHaskell2010

Pipes

Contents

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

The Proxy Monad Transformer

data Proxy a' a b' b m r Source

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) Source 
MonadReader r m => MonadReader r (Proxy a' a b' b m) Source 
MonadState s m => MonadState s (Proxy a' a b' b m) Source 
MonadWriter w m => MonadWriter w (Proxy a' a b' b m) Source 
MFunctor (Proxy a' a b' b) Source 
MMonad (Proxy a' a b' b) Source 
MonadTrans (Proxy a' a b' b) Source 
Monad m => Monad (Proxy a' a b' b m) Source 
Monad m => Functor (Proxy a' a b' b m) Source 
Monad m => Applicative (Proxy a' a b' b m) Source 
MonadThrow m => MonadThrow (Proxy a' a b' b m) Source 
MonadCatch m => MonadCatch (Proxy a' a b' b m) Source 
MonadIO m => MonadIO (Proxy a' a b' b m) Source 
(Monad m, Monoid r) => Monoid (Proxy a' a b' b m r) Source 

data X Source

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 Source

An effect in the base monad

Effects neither await nor yield

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

Like Effect, but with a polymorphic type

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

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

Producers

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

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 Source

Producers can only yield

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

Like Producer, but with a polymorphic type

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

Produce a value

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

for Source

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 Source

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 Source

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

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 Source

Consumers can only await

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

Like Consumer, but with a polymorphic type

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

Consume a value

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

(>~) infixr 5 Source

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 Source

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 Pipes and (>->) to connect Pipes.

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 Source

Pipes can both await and yield

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

The identity Pipe, analogous to the Unix cat program

(>->) infixl 7 Source

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 Source

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 Source

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

Constructors

Select 

Fields

enumerate :: Producer a m ()
 

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

Run a self-contained ListT computation

class Enumerable t where Source

Enumerable generalizes Foldable, converting effectful containers to ListTs.

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 Source

Utilities

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

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

Convert a Foldable to a Producer

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

Convert an Enumerable to a Producer

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

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

class Foldable t

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)

Minimal complete definition

foldMap | foldr