bluefin-0.7.0.0: src/Bluefin/Capability/Request.hs
module Bluefin.Capability.Request
( -- | @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 @Request@s.
-- ** Prompt finalization/resource safety
-- | Bluefin
-- t'Bluefin.Capability.Yield.Yield' \/ t'Bluefin.Capability.Await.Await' \/ t'Bluefin.Capability.Request.Request'
-- computations have much better resource safety properties than
-- Conduit and Pipes. You can use
-- @Bluefin.Eff.'Bluefin.Eff.bracket'@ 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 @ResourceT@ scope as it is the case in Conduit and Pipes.
-- See the blog post [Bluefin streams finalize
-- promptly](https://h2.jaguarpaw.co.uk/posts/bluefin-streams-finalize-promptly/)
-- for more details.
-- ** Running coroutines that communicate via @Request@s
-- | Bluefin operations can be executed as coroutines using
-- 'connectRequests' ([Wikipedia
-- suggests](https://en.wikipedia.org/wiki/Coroutine#Definition_and_types)
-- that such coroutines are "second-class stackful coroutines").
-- Two coroutines run in this way communicate synchronously by
-- using @Request@s 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.
--
-- @Request@s 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 @a@s
-- and receives a @b@s. 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:
-- @'Bluefin.Capability.Yield.Yield' a@ and
-- @'Bluefin.Capability.Await.Await' a@, respectively. The
-- specializations of @request@ for @Yield@ and @Await@ are called
-- 'Bluefin.Capability.Yield.yield' and
-- 'Bluefin.Capability.Await.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
Request,
-- * Handlers
forEach,
connectRequests,
-- * Effectful operations
request,
)
where
import Bluefin.Internal