pipes-4.3.7: Compositional pipelines

Safe HaskellTrustworthy
LanguageHaskell2010

Pipes.Core

Contents

Description

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

Synopsis

Proxy Monad Transformer

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:

  • (>+>): connect pull-based streams
  • (>~>): connect push-based streams
  • (\>\): chain folds
  • (/>/): chain unfolds
  • (>=>): sequence proxies

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 # 

Methods

throwError :: e -> Proxy a' a b' b m a #

catchError :: Proxy a' a b' b m a -> (e -> Proxy a' a b' b m a) -> Proxy a' a b' b m a #

MonadReader r m => MonadReader r (Proxy a' a b' b m) Source # 

Methods

ask :: Proxy a' a b' b m r #

local :: (r -> r) -> Proxy a' a b' b m a -> Proxy a' a b' b m a #

reader :: (r -> a) -> Proxy a' a b' b m a #

MonadState s m => MonadState s (Proxy a' a b' b m) Source # 

Methods

get :: Proxy a' a b' b m s #

put :: s -> Proxy a' a b' b m () #

state :: (s -> (a, s)) -> Proxy a' a b' b m a #

MonadWriter w m => MonadWriter w (Proxy a' a b' b m) Source # 

Methods

writer :: (a, w) -> Proxy a' a b' b m a #

tell :: w -> Proxy a' a b' b m () #

listen :: Proxy a' a b' b m a -> Proxy a' a b' b m (a, w) #

pass :: Proxy a' a b' b m (a, w -> w) -> Proxy a' a b' b m a #

MFunctor * (Proxy a' a b' b) Source # 

Methods

hoist :: Monad m => (forall c. m c -> n c) -> t m b -> t n b #

MMonad (Proxy a' a b' b) Source # 

Methods

embed :: Monad n => (forall c. m c -> Proxy a' a b' b n c) -> Proxy a' a b' b m b -> Proxy a' a b' b n b #

MonadTrans (Proxy a' a b' b) Source # 

Methods

lift :: Monad m => m a -> Proxy a' a b' b m a #

Monad m => Monad (Proxy a' a b' b m) Source # 

Methods

(>>=) :: Proxy a' a b' b m a -> (a -> Proxy a' a b' b m b) -> Proxy a' a b' b m b #

(>>) :: Proxy a' a b' b m a -> Proxy a' a b' b m b -> Proxy a' a b' b m b #

return :: a -> Proxy a' a b' b m a #

fail :: String -> Proxy a' a b' b m a #

Monad m => Functor (Proxy a' a b' b m) Source # 

Methods

fmap :: (a -> b) -> Proxy a' a b' b m a -> Proxy a' a b' b m b #

(<$) :: a -> Proxy a' a b' b m b -> Proxy a' a b' b m a #

Monad m => Applicative (Proxy a' a b' b m) Source # 

Methods

pure :: a -> Proxy a' a b' b m a #

(<*>) :: Proxy a' a b' b m (a -> b) -> Proxy a' a b' b m a -> Proxy a' a b' b m b #

(*>) :: Proxy a' a b' b m a -> Proxy a' a b' b m b -> Proxy a' a b' b m b #

(<*) :: Proxy a' a b' b m a -> Proxy a' a b' b m b -> Proxy a' a b' b m a #

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

Methods

liftIO :: IO a -> Proxy a' a b' b m a #

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

Methods

throwM :: Exception e => e -> Proxy a' a b' b m a #

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

Methods

catch :: Exception e => Proxy a' a b' b m a -> (e -> Proxy a' a b' b m a) -> Proxy a' a b' b m a #

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

Methods

(<>) :: Proxy a' a b' b m r -> Proxy a' a b' b m r -> Proxy a' a b' b m r #

sconcat :: NonEmpty (Proxy a' a b' b m r) -> Proxy a' a b' b m r #

stimes :: Integral b => b -> Proxy a' a b' b m r -> Proxy a' a b' b m r #

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

Methods

mempty :: Proxy a' a b' b m r #

mappend :: Proxy a' a b' b m r -> Proxy a' a b' b m r -> Proxy a' a b' b m r #

mconcat :: [Proxy a' a b' b m r] -> Proxy a' a b' b m r #

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

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

Categories

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

-- Left identity
id . f = f

-- Right identity
f . id = f

-- Associativity
(f . g) . h = f . (g . 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    |     >=>     |     >>=     |
                  +-------------+-------------+-------------+

Each composition operator has a "point-ful" version, analogous to how (>>=) is the point-ful version of (>=>). 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)

The following diagrams show the flow of information:

respond :: Monad m
       =>  a -> Proxy x' x a' a m a'

          a
          |
     +----|----+
     |    |    |
 x' <==   \ /==== a'
     |     X   |
 x  ==>   / \===> a
     |    |    |
     +----|----+
          v
          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')

          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'

(//>) :: Monad 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'

respond :: Monad m => a -> Proxy x' x a' a m a' Source #

Send a value of type a downstream and block waiting for a reply of type a'

respond is the identity of the respond category.

(/>/) 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 two unfolds, creating a new unfold

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

(/>/) is the composition operator of the respond category.

(//>) infixl 3 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' 

(p //> f) replaces each respond in p with f.

Point-ful version of (/>/)

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)

The following diagrams show the flow of information:

request :: Monad m
        =>  a' -> Proxy a' a y' y m a

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

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

          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

(>\\) :: Monad 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

request :: Monad m => a' -> Proxy a' a y' y m a Source #

Send a value of type a' upstream and block waiting for a reply of type a

request is the identity of the request category.

(\>\) infixl 5 Source #

Arguments

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

Compose two folds, creating a new fold

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

(\>\) is the composition operator of the request category.

(>\\) infixr 4 Source #

Arguments

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

(f >\\ p) replaces each request in p with f.

Point-ful version of (\>\)

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  :: Monad m
      =>  a -> Proxy a' a a' a m r

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

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

          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

push :: Monad m => a -> Proxy a' a a' a m r Source #

Forward responses followed by requests

push = respond >=> request >=> push

push is the identity of the push category.

(>~>) infixr 8 Source #

Arguments

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

Compose two proxies blocked while requesting data, creating a new proxy blocked while requesting data

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

(>~>) is the composition operator of the push category.

(>>~) infixl 7 Source #

Arguments

:: 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 >>~ f) pairs each respond in p with a request in f.

Point-ful version of (>~>)

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)

The following diagrams show the flow of information:

pull  :: Monad m
      =>  a' -> Proxy a' a a' a m r

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

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

          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

pull :: Monad m => a' -> Proxy a' a a' a m r Source #

Forward requests followed by responses:

pull = request >=> respond >=> pull

pull is the identity of the pull category.

(>+>) infixl 7 Source #

Arguments

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

Compose two proxies blocked in the middle of responding, creating a new proxy blocked in the middle of responding

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

(>+>) is the composition operator of the pull category.

(+>>) infixr 6 Source #

Arguments

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

(f +>> p) pairs each request in p with a respond in f.

Point-ful version of (>+>)

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

reflect :: Monad m => Proxy a' a b' b m r -> Proxy b b' a a' m r Source #

Switch the upstream and downstream ends

Concrete Type Synonyms

type X = Void Source #

The empty type, used to close output ends

type Effect = Proxy X () () X Source #

An effect in the base monad

Effects neither await nor yield

type Producer b = Proxy X () () b Source #

Producers can only yield

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

Pipes can both await and yield

type Consumer a = Proxy () a () X Source #

Consumers can only await

type Client a' a = Proxy a' a () X Source #

Client a' a sends requests of type a' and receives responses of type a.

Clients only request and never respond.

type Server b' b = Proxy X () b' b Source #

Server b' b receives requests of type b' and sends responses of type b.

Servers only respond and never request.

Polymorphic Type Synonyms

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

Like Effect, but with a polymorphic type

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

Like Producer, but with a polymorphic type

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

Like Consumer, but with a polymorphic type

type Client' a' a m r = forall y' y. Proxy a' a y' y m r Source #

Like Client, but with a polymorphic type

type Server' b' b m r = forall x' x. Proxy x' x b' b m r Source #

Like Server, but with a polymorphic type

Flipped operators

(\<\) 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' 

Equivalent to (/>/) with the arguments flipped

(/</) infixr 5 Source #

Arguments

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

Equivalent to (\>\) with the arguments flipped

(<~<) infixl 8 Source #

Arguments

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

Equivalent to (>~>) with the arguments flipped

(~<<) infixr 7 Source #

Arguments

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

Equivalent to (>>~) with the arguments flipped

(<+<) infixr 7 Source #

Arguments

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

Equivalent to (>+>) with the arguments flipped

(<\\) infixr 3 Source #

Arguments

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

Equivalent to (//>) with the arguments flipped

(//<) infixl 4 Source #

Arguments

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

Equivalent to (>\\) with the arguments flipped

(<<+) infixl 6 Source #

Arguments

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

Equivalent to (+>>) with the arguments flipped

Re-exports

closed :: X -> a Source #

Use closed to "handle" impossible outputs