pipes-2.4.0: Compositional pipelines

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 # Methodsfmap :: (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 FieldsunProxy :: FreeT (ProxyF a' a b' b) m r Instances  Source # Methodsrequest :: 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 #(/ (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 # Source # MethodsidT :: 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 # Methodslift :: Monad m => m a -> Proxy a' a b' b m a # MFunctor (Proxy a' a b' b) Source # MethodsmapT :: (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 # Methodsfmap :: (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 # Methodspure :: 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 # MethodsliftIO :: 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 #