| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Bluefin.Capability.Request
Synopsis
- type Request = Coroutine
- forEach :: forall a b (es :: Effects) r. (forall (e1 :: Effects). Coroutine a b e1 -> Eff (e1 :& es) r) -> (a -> Eff es b) -> Eff es r
- connectRequests :: forall (es :: Effects) a b r. (forall (e :: Effects). Request a b e -> Eff (e :& es) r) -> (forall (e :: Effects). a -> Request b a e -> Eff (e :& es) r) -> Eff es r
- request :: forall (e1 :: Effects) (es :: Effects) a b. e1 <: es => Request a b e1 -> a -> Eff es b
Documentation
Request allows to yield values and await the result. You
might want to start with Bluefin.Capability.Yield, which is
the most common way to use Requests.
Prompt finalization/resource safety
Bluefin
Yield / Await / Request
computations have much better resource safety properties than
Conduit and Pipes. You can use
Bluefin.Eff. within a streaming
computation and the acquired resource is guaranteed to be
released and the end of the bracket, rather than at the end of
the bracketResourceT scope as it is the case in Conduit and Pipes.
See the blog post Bluefin streams finalize
promptly
for more details.
Running coroutines that communicate via Requests
Bluefin operations can be executed as coroutines using
connectRequests (Wikipedia
suggests
that such coroutines are "second-class stackful coroutines").
Two coroutines run in this way communicate synchronously by
using Requests to interact with a bi-directional
channel. This means that such coroutines are often run
exclusively for what they communicate via this channel, not
for their return value.
Requests used in this way work a bit like UNIX pipes: there
is a downstream consumer and an upstream generator. For every
pair of such communicating coroutines there are two ends,
represented with the capabilities Request a b and Request b
a. The first parameter to Request is the type that can be
sent from that end, while the second parameter is the type
that will subsequently be received by that end. This explains
the symmetry in the capabilities: what one end sends the other
receives. The implication is that upstream and downstream
exchange messages with each other at the same
time. Additionally, there is a clear order of communication
from the start (in Bluefin, communication is started by
upstream).
request is the only effectful operation required: a Request
a b capability that represents one end of a channel sends as
and receives a bs. For many use cases, upstream does not need
to know anything from downstream (dually: downstream does not
need to communicate anything to upstream) except that
downstream is making a new request, so the capabilities that
describe most channels are "Request a ()" and "Request ()
a". Bluefin provides synonyms for these:
and
Yield a, respectively. The
specializations of Await arequest for Yield and Await are called
yield and
await. Coroutines that send data in
only one direction like this can be created using awaitYield.
Because the message exchange occurs synchronously, when yielding, the upstream will block until the downstream awaits. The converse is also true: when downstream awaits, it will block until upstream yields.
Any Bluefin effectful operation that takes a Request
capability as an argument can be run as coroutine using
connectRequests by providing a second effectful operation
as its counterpart on the other end of the channel.
For simple applications one may not need connectRequests at
all, because specific handlers are already provided by
Bluefin. See the "Handlers" sections of the
Bluefin.Capability.Yield and Bluefin.Capability.Await
modules.
Capability
Capability to yield a value of type a and then await a value of
type b in response.
Handlers
Arguments
| :: forall a b (es :: Effects) r. (forall (e1 :: Effects). Coroutine a b e1 -> Eff (e1 :& es) r) | |
| -> (a -> Eff es b) | Apply this effectful function for each element of the coroutine |
| -> Eff es r |
Apply an effectful function to each element yielded to the stream.
>>>runPureEff$yieldToList$ \y -> doforEach(inFoldable[0 .. 3]) $ \i -> doyieldy i yield y (i * 10) ([0, 0, 1, 10, 2, 20, 3, 30], ())
Arguments
| :: forall (es :: Effects) a b r. (forall (e :: Effects). Request a b e -> Eff (e :& es) r) | |
| -> (forall (e :: Effects). a -> Request b a e -> Eff (e :& es) r) | |
| -> Eff es r | ͘ |
Interleave the execution of two Bluefin operations by sending
their requests to each other. as are sent from the first to the
second which responds by returning bs. The first runs until it
yields its first a it starts the second (which is awaiting an
a).