Safe Haskell | Safe |
---|---|
Language | Haskell2010 |
A Proxy
request
s input from upstream and respond
s with output to
downstream.
For an extended tutorial, consult Control.Proxy.Tutorial.
- data ProxyF a' a b' b x
- newtype Proxy a' a b' b m r = Proxy {}
- 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
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 interfaceresp_a
- The response provided by the upstream interfacereq_b
- The request supplied by the downstream interfaceresp_b
- The response provided to the downstream interfacem
- The base monadr
- The final return value
newtype Proxy a' a b' b m r Source #
A Proxy
converts one interface to another
Interact Proxy Source # | |
Channel Proxy Source # | |
MonadTrans (Proxy a' a b' b) Source # | |
MFunctor (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 # | |
MonadIO m => MonadIO (Proxy a' a b' b m) Source # | |
Run Sessions
I provide two ways to run proxies:
runProxy
, which discards unhandled output from either endrunSession
, 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