| Safe Haskell | Safe-Inferred |
|---|
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.
- data Proxy a' a b' b m r
- data C
- type Server req resp = Proxy C () req resp
- type Client req resp = Proxy req resp () C
- type Session = Proxy C () () C
- runProxy :: Monad m => (() -> Proxy a' () () b m r) -> m r
- runProxyK :: Monad m => (() -> Proxy a () () b m r) -> () -> m r
- runSession :: Monad m => (() -> Session m r) -> m r
- runSessionK :: Monad m => (() -> Session m r) -> () -> m r
- discard :: Monad m => () -> Proxy () a () C m r
- ignore :: Monad m => a -> Proxy C () a () m r
Types
data Proxy a' a b' b m r Source
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
Constructors
| Request a' (a -> Proxy a' a b' b m r) | |
| Respond b (b' -> Proxy a' a b' b m r) | |
| M (m (Proxy a' a b' b m r)) | |
| Pure r |
Instances
| Interact Proxy | |
| Channel Proxy | |
| MonadTrans (Proxy a' a b' b) | |
| MFunctor (Proxy a' a b' b) | |
| Monad m => Monad (Proxy a' a b' b m) | |
| Monad m => Functor (Proxy a' a b' b m) | |
| (Functor (Proxy a' a b' b m), Monad m) => Applicative (Proxy a' a b' b m) | |
| (Monad (Proxy a' a b' b m), MonadIO m) => MonadIO (Proxy a' a b' b m) |
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 rSource
Run a self-sufficient Proxy Kleisli arrow, converting it back to the base
monad
runProxyK :: Monad m => (() -> Proxy a () () b m r) -> () -> m rSource
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 rSource
Run a self-contained Session Kleisli arrow, converting it back to the base
monad
runSessionK :: Monad m => (() -> Session m r) -> () -> m rSource
Run a self-contained Session Kleisli arrow, converting it back to a
Kleisli arrow in the base monad