Safe Haskell | Trustworthy |
---|---|
Language | Haskell2010 |
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
Pipe
s.
- data Proxy a' a b' b m r
- runEffect :: Monad m => Effect m r -> m r
- respond :: Monad m => a -> Proxy x' x a' a m 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'
- (//>) :: Monad m => Proxy x' x b' b m a' -> (b -> Proxy x' x c' c m b') -> Proxy x' x c' c m a'
- request :: Monad m => a' -> Proxy a' a y' y m 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
- (>\\) :: Monad m => (b' -> Proxy a' a y' y m b) -> Proxy b' b y' y m c -> Proxy a' a y' y m c
- push :: Monad m => a -> Proxy a' a a' a m 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
- (>>~) :: Monad m => Proxy a' a b' b m r -> (b -> Proxy b' b c' c m r) -> Proxy a' a c' c m r
- pull :: Monad m => a' -> Proxy a' a a' a m 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
- (+>>) :: Monad m => (b' -> Proxy a' a b' b m r) -> Proxy b' b c' c m r -> Proxy a' a c' c m r
- reflect :: Monad m => Proxy a' a b' b m r -> Proxy b b' a a' m r
- data X
- type Effect = Proxy X () () X
- type Producer b = Proxy X () () b
- type Pipe a b = Proxy () a () b
- type Consumer a = Proxy () a () X
- type Client a' a = Proxy a' a () X
- type Server b' b = Proxy X () b' b
- type Effect' m r = forall x' x y' y. Proxy x' x y' y m r
- type Producer' b m r = forall x' x. Proxy x' x () b m r
- type Consumer' a m r = forall y' y. Proxy () a y' y m r
- type Client' a' a m r = forall y' y. Proxy a' a y' y m r
- type Server' b' b m r = forall x' x. Proxy x' x b' b m r
- (\<\) :: 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'
- (/</) :: 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
- (<~<) :: 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
- (~<<) :: Monad m => (b -> Proxy b' b c' c m r) -> Proxy a' a b' b m r -> Proxy a' a c' c m r
- (<+<) :: 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
- (<\\) :: Monad m => (b -> Proxy x' x c' c m b') -> Proxy x' x b' b m a' -> Proxy x' x c' c m a'
- (//<) :: Monad m => Proxy b' b y' y m c -> (b' -> Proxy a' a y' y m b) -> Proxy a' a y' y m c
- (<<+) :: Monad m => Proxy b' b c' c m r -> (b' -> Proxy a' a b' b m r) -> Proxy a' a c' c m r
- closed :: X -> a
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:
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'
anda
- The upstream interface, where(a')
s go out and(a)
s come inb'
andb
- The downstream interface, where(b)
s go out and(b')
s come inm
- The base monadr
- The return value
MonadError e m => MonadError e (Proxy a' a b' b m) Source | |
MonadReader r m => MonadReader r (Proxy a' a b' b m) Source | |
MonadState s m => MonadState s (Proxy a' a b' b m) Source | |
MonadWriter w m => MonadWriter w (Proxy a' a b' b m) Source | |
MFunctor (Proxy a' a b' b) Source | |
MMonad (Proxy a' a b' b) Source | |
MonadTrans (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 | |
MonadThrow m => MonadThrow (Proxy a' a b' b m) Source | |
MonadCatch m => MonadCatch (Proxy a' a b' b m) Source | |
MonadIO m => MonadIO (Proxy a' a b' b m) Source | |
(Monad m, Monoid r) => Monoid (Proxy a' a b' b m r) Source |
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 identityid
.
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 identityrespond
/>/
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.
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 identityrequest
\>\
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.
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 identitypush
>~>
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
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 identitypull
>+>
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
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
The empty type, used to close output ends
When Data.Void
is merged into base
, this will change to:
type X = Void
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
:: 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
:: 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
Equivalent to (>~>
) with the arguments flipped
Equivalent to (>>~
) with the arguments flipped
:: 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
Equivalent to (//>
) with the arguments flipped
Equivalent to (>\\
) with the arguments flipped
Equivalent to (+>>
) with the arguments flipped