pipes-2.4.0: Compositional pipelines

Safe HaskellSafe
LanguageHaskell2010

Control.Proxy.Core

Contents

Description

A Proxy requests input from upstream and responds with output to downstream.

For an extended tutorial, consult Control.Proxy.Tutorial.

Synopsis

Types

A Proxy communicates with an upstream interface and a downstream interface.

The type variables of Proxy req_a resp_a req_b resp_b m r signify:

  • req_a - The request supplied to the upstream interface
  • resp_a - The response provided by the upstream interface
  • req_b - The request supplied by the downstream interface
  • resp_b - The response provided to the downstream interface
  • m - The base monad
  • r - The final return value

data ProxyF a' a b' b x Source #

The base functor for the Proxy type

Constructors

Request a' (a -> x) 
Respond b (b' -> x) 

Instances

Functor (ProxyF a' a b' b) Source # 

Methods

fmap :: (a -> b) -> ProxyF a' a b' b a -> ProxyF a' a b' b b #

(<$) :: a -> ProxyF a' a b' b b -> ProxyF a' a b' b a #

newtype Proxy a' a b' b m r Source #

A Proxy converts one interface to another

Constructors

Proxy 

Fields

Instances

Interact Proxy Source # 

Methods

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

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

(/</) :: 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 Source #

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

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

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

Channel Proxy Source # 

Methods

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

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

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

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

Methods

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

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

Methods

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

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 #

data C Source #

The empty type, denoting a 'C'losed end

type Server req resp = Proxy C () req resp Source #

Server req resp receives requests of type req and sends responses of type resp.

Servers only respond and never request anything.

type Client req resp = Proxy req resp () C Source #

Client req resp sends requests of type req and receives responses of type resp.

Clients only request and never respond to anything.

type Session = Proxy C () () C Source #

A self-contained Session, ready to be run by runSession

Sessions never request anything or respond to anything.

Run Sessions

I provide two ways to run proxies:

  • runProxy, which discards unhandled output from either end
  • runSession, which type restricts its argument to ensure no loose ends

Both functions require that the input to each end is trivially satisfiable, (i.e. ()).

I recommend runProxy for most use cases since it is more convenient.

runSession only accepts sessions that do not send unhandled data flying off each end, which provides the following benefits:

  • It prevents against accidental data loss.
  • It protects against silent failures
  • It prevents wastefully draining a scarce resource by gratuitously driving it to completion

However, this restriction means that you must either duplicate every utility function to specialize them to the end-point positions (which I do not do), or explicitly close loose ends using the discard and ignore proxies:

runSession $ discard <-< p <-< ignore

Use the 'K' versions of each command if you are running sessions nested within sessions. They provide a Kleisli arrow as their result suitable to be passed to another runProxy / runSession command.

runProxy :: Monad m => (() -> Proxy a () () b m r) -> m r Source #

Run a self-sufficient Proxy Kleisli arrow, converting it back to the base monad

runProxyK :: Monad m => (() -> Proxy a () () b m r) -> () -> m r Source #

Run a self-sufficient Proxy Kleisli arrow, converting it back to a Kleisli arrow in the base monad

runSession :: Monad m => (() -> Session m r) -> m r Source #

Run a self-contained Session Kleisli arrow, converting it back to the base monad

runSessionK :: Monad m => (() -> Session m r) -> () -> m r Source #

Run a self-contained Session Kleisli arrow, converting it back to a Kleisli arrow in the base monad

Utility Proxies

discard provides a fallback client that gratuitously requests input from a server, but discards all responses.

ignore provides a fallback server that trivially responds with output to a client, but ignores all request parameters.

discard :: Monad m => () -> Proxy () a () C m r Source #

Discard all responses

ignore :: Monad m => a -> Proxy C () a () m r Source #

Ignore all requests