Asynchronous Programming Primitives #
This module provides a layered approach to asynchronous programming, combining monadic types, type classes, and concrete task types that work together in a cohesive system.
- Monadic Types: These types provide a good way to to chain and manipulate context. These
can contain a
Task
, enabling manipulation of both asynchronous and synchronous code. - Concrete Task Types: Concrete units of work that can be executed within these contexts.
Monadic Types #
These types provide a good way to to chain and manipulate context. These can contain a Task
,
enabling manipulation of both asynchronous and synchronous code.
BaseAsync
: A monadic type for infallible asynchronous computationsEAsync
: A monadic type for asynchronous computations that may fail with an error of typeε
Async
: A monadic type for IO-based asynchronous computations that may fail withIO.Error
(alias forEAsync IO.Error
)
Concurrent Units of Work #
These are the concrete computational units that exist within the monadic contexts. These types should not be created directly.
Task
: A computation that will resolve to a value of typeα
,ETask
: A task that may fail with an error of typeε
.AsyncTask
: A task that may fail with anIO.Error
(alias forETask IO.Error
).
Relation #
These types are related by two functions in the type classes MonadAsync
and MonadAwait
: async
and await
. The async
function extracts a concrete asynchronous task from a computation within the
monadic context. In effect, it runs the computation in the background and returns a task handle that
can be awaited later. On the other hand, the await
function takes a task and re-inserts it into the
monadic context, allowing its result to be composed using monadic bind and also pausing to wait for that result.
This relationship between async
and await
enables precise control over when a computation begins
and when its result is used. You can spawn multiple asynchronous tasks using async
, perform other
operations in the meantime, and later rejoin the computation flow by awaiting their results.
These functions should not be used directly. Instead, prefer higher-level combinators such as
race
, raceAll
, concurrently
, background
and concurrentlyAll
. The best way to think about
how to write your async code, it to avoid using the concurrent units of work, and only use it when integrating
with non async code that uses them.
Typeclass for monads that can "await" a computation of type t α
in a monad m
until the result is
available.
- await {α : Type} : t α → m α
Awaits the result of
t α
and returns it inside them
monad.
Instances
- Std.Internal.IO.Async.Async.instMonadAwaitAsyncTask
- Std.Internal.IO.Async.Async.instMonadAwaitPromise
- Std.Internal.IO.Async.BaseAsync.instMonadAwaitTask
- Std.Internal.IO.Async.EAsync.instMonadAwaitAsyncTaskError
- Std.Internal.IO.Async.EAsync.instMonadAwaitETask
- Std.Internal.IO.Async.EAsync.instMonadAwaitPromise
- Std.Internal.IO.Async.EAsync.instMonadAwaitTask
- Std.Internal.IO.Async.instMonadAwaitExceptTOfMonad
- Std.Internal.IO.Async.instMonadAwaitReaderTOfMonad
- Std.Internal.IO.Async.instMonadAwaitStateRefT'
- Std.Internal.IO.Async.instMonadAwaitStateT
- Std.Internal.IO.Async.instMonadAwaitStateTOfMonad
Represents monads that can launch computations asynchronously of type t
in a monad m
.
Starts an asynchronous computation in another monad.
Instances
- Std.Internal.IO.Async.Async.instMonadAsyncAsyncTask
- Std.Internal.IO.Async.BaseAsync.instMonadAsyncTask
- Std.Internal.IO.Async.EAsync.instMonadAsyncAsyncTaskError
- Std.Internal.IO.Async.EAsync.instMonadAsyncETask
- Std.Internal.IO.Async.instMonadAsyncReaderT
- Std.Internal.IO.Async.instMonadAsyncStateRefT'
- Std.Internal.IO.Async.instMonadAsyncStateTOfFunctor
Equations
- Std.Internal.IO.Async.instMonadAwaitStateTOfMonad = { toMonad := StateT.instMonad, await := fun {α : Type} => liftM ∘ Std.Internal.IO.Async.await }
Equations
- Std.Internal.IO.Async.instMonadAwaitExceptTOfMonad = { toMonad := ExceptT.instMonad, await := fun {α : Type} => liftM ∘ Std.Internal.IO.Async.await }
Equations
- Std.Internal.IO.Async.instMonadAwaitReaderTOfMonad = { toMonad := ReaderT.instMonad, await := fun {α : Type} => liftM ∘ Std.Internal.IO.Async.await }
Equations
- Std.Internal.IO.Async.instMonadAwaitStateRefT' = { toMonad := StateRefT'.instMonad, await := fun {α : Type} => liftM ∘ Std.Internal.IO.Async.await }
Equations
- Std.Internal.IO.Async.instMonadAwaitStateT = { toMonad := StateT.instMonad, await := fun {α : Type} => liftM ∘ Std.Internal.IO.Async.await }
Equations
- One or more equations did not get rendered due to their size.
Equations
- One or more equations did not get rendered due to their size.
Equations
- One or more equations did not get rendered due to their size.
A Task
that may resolve to either a value of type α
or an error value of type ε
.
Equations
- Std.Internal.IO.Async.ETask ε α = ExceptT ε Task α
Creates a new ETask
that will run after x
has finished. If x
:
Equations
- Std.Internal.IO.Async.ETask.map f x prio sync = Task.map (fun (x : Except ε α) => f <$> x) x prio sync
Creates a new ETask
that will run after x
has completed. If x
:
- errors, return an
ETask
that resolves to the error. - succeeds, run
f
on the result ofx
and return theETask
produced byf
.
Equations
- x.bind f prio sync = Task.bind x (fun (x : Except ε α) => match x with | Except.ok a => f a | Except.error e => { get := Except.error e }) prio sync
Similar to bind
, however f
has access to the EIO
monad. If f
throws an error, the returned
ETask
resolves to that error.
Equations
- One or more equations did not get rendered due to their size.
Similar to bind
, however f
has access to the EIO
monad. If f
throws an error, the returned
ETask
resolves to that error.
Equations
- One or more equations did not get rendered due to their size.
Block until the ETask
in x
finishes and returns its value. Propagates any error encountered
during execution.
Equations
- x.block = match x.get with | Except.ok a => pure a | Except.error e => EStateM.Result.error e
Create an ETask
that resolves to the pure value of the promise x
.
Equations
- Std.Internal.IO.Async.ETask.instFunctor = { map := fun {α β : Type} (f : α → β) (x : Std.Internal.IO.Async.ETask ε α) => Std.Internal.IO.Async.ETask.map f x }
Equations
- One or more equations did not get rendered due to their size.
Similar to map
, however f
has access to the IO
monad. If f
throws an error, the returned
AsyncTask
resolves to that error.
Equations
- One or more equations did not get rendered due to their size.
Create a new AsyncTask
that will run after x
has finished.
If x
:
- errors, return an
AsyncTask
that resolves to the error. - succeeds, run
f
on the result ofx
and return theAsyncTask
produced byf
.
Equations
- x.bind f prio sync = Task.bind x (fun (x : Except IO.Error α) => match x with | Except.ok a => f a | Except.error e => { get := Except.error e }) prio sync
Create a new AsyncTask
that will run after x
has finished.
If x
:
Similar to bind
, however f
has access to the IO
monad. If f
throws an error, the returned
AsyncTask
resolves to that error.
Equations
- x.bindIO f prio sync = IO.bindTask x (fun (x : Except IO.Error α) => match x with | Except.ok a => f a | Except.error e => EStateM.Result.error e) prio sync
Similar to map
, however f
has access to the IO
monad. If f
throws an error, the returned
AsyncTask
resolves to that error.
Equations
- One or more equations did not get rendered due to their size.
Block until the AsyncTask
in x
finishes.
Equations
- x.block = match x.get with | Except.ok a => pure a | Except.error e => EStateM.Result.error e
Create an AsyncTask
that resolves to the value of x
.
Equations
Create an AsyncTask
that resolves to the value of x
.
A MaybeTask α
represents a computation that either:
- Is immediately available as an
α
value, or - Is an asynchronous computation that will eventually produce an
α
value.
Constructs an Task
from a MaybeTask
.
Equations
- (Std.Internal.IO.Async.MaybeTask.pure a).toTask = { get := a }
- (Std.Internal.IO.Async.MaybeTask.ofTask t).toTask = t
Maps a function over a MaybeTask
.
Equations
- Std.Internal.IO.Async.MaybeTask.map f prio sync (Std.Internal.IO.Async.MaybeTask.pure a) = Std.Internal.IO.Async.MaybeTask.pure (f a)
- Std.Internal.IO.Async.MaybeTask.map f prio sync (Std.Internal.IO.Async.MaybeTask.ofTask t) = Std.Internal.IO.Async.MaybeTask.ofTask (Task.map f t prio sync)
Sequences two computations, allowing the second to depend on the value computed by the first.
Equations
- (Std.Internal.IO.Async.MaybeTask.pure a).bind f prio sync = f a
- (Std.Internal.IO.Async.MaybeTask.ofTask t_1).bind f prio sync = Std.Internal.IO.Async.MaybeTask.ofTask (t_1.bind (fun (x : α) => (f x).toTask) prio sync)
Equations
- Std.Internal.IO.Async.MaybeTask.instFunctor = { map := fun {α β : Type} (f : α → β) => Std.Internal.IO.Async.MaybeTask.map f }
Equations
- One or more equations did not get rendered due to their size.
An asynchronous computation that never fails.
Equations
Instances For
- Std.Internal.IO.Async.BaseAsync.instFunctor
- Std.Internal.IO.Async.BaseAsync.instInhabited
- Std.Internal.IO.Async.BaseAsync.instMonad
- Std.Internal.IO.Async.BaseAsync.instMonadAsyncTask
- Std.Internal.IO.Async.BaseAsync.instMonadAwaitTask
- Std.Internal.IO.Async.BaseAsync.instMonadLiftBaseIO
- Std.Internal.IO.Async.EAsync.instMonadLiftBaseAsync
Creates a BaseAsync
computation that immediately returns the given value.
Maps the result of a BaseAsync
computation with a function.
Equations
- One or more equations did not get rendered due to their size.
Sequences two computations, allowing the second to depend on the value computed by the first.
Equations
- self.bind f prio sync = Std.Internal.IO.Async.BaseAsync.mk do let x ← self.toRawBaseIO (Std.Internal.IO.Async.BaseAsync.bind.bindAsyncTask prio sync x f).toRawBaseIO
Equations
- One or more equations did not get rendered due to their size.
- Std.Internal.IO.Async.BaseAsync.bind.bindAsyncTask prio sync (Std.Internal.IO.Async.MaybeTask.pure a) f = Std.Internal.IO.Async.BaseAsync.mk (f a).toRawBaseIO
Lifts a BaseAsync
computation into a Task
that can be awaited and joined.
Equations
- x.asTask prio = do let res ← x.toRawBaseIO.asTask prio pure (Std.Internal.IO.Async.MaybeTask.joinTask res)
Returns the BaseAsync
computation inside a Task α
, so it can be awaited.
Equations
- self.async prio = Std.Internal.IO.Async.BaseAsync.lift (self.asTask prio)
Equations
- Std.Internal.IO.Async.BaseAsync.instFunctor = { map := fun {α β : Type} (f : α → β) (self : Std.Internal.IO.Async.BaseAsync α) => Std.Internal.IO.Async.BaseAsync.map f self }
Equations
- One or more equations did not get rendered due to their size.
Equations
- Std.Internal.IO.Async.BaseAsync.instMonadLiftBaseIO = { monadLift := fun {α : Type} => Std.Internal.IO.Async.BaseAsync.lift }
Equations
- Std.Internal.IO.Async.BaseAsync.instMonadAwaitTask = { toMonad := Std.Internal.IO.Async.BaseAsync.instMonad, await := fun {α : Type} => Std.Internal.IO.Async.BaseAsync.await }
Equations
- One or more equations did not get rendered due to their size.
An asynchronous computation that may produce an error of type ε
.
Equations
Instances For
- Std.Internal.IO.Async.EAsync.instForInLoopUnitOfInhabited
- Std.Internal.IO.Async.EAsync.instFunctor
- Std.Internal.IO.Async.EAsync.instInhabited
- Std.Internal.IO.Async.EAsync.instMonad
- Std.Internal.IO.Async.EAsync.instMonadAsyncAsyncTaskError
- Std.Internal.IO.Async.EAsync.instMonadAsyncETask
- Std.Internal.IO.Async.EAsync.instMonadAwaitAsyncTaskError
- Std.Internal.IO.Async.EAsync.instMonadAwaitETask
- Std.Internal.IO.Async.EAsync.instMonadAwaitPromise
- Std.Internal.IO.Async.EAsync.instMonadAwaitTask
- Std.Internal.IO.Async.EAsync.instMonadExcept
- Std.Internal.IO.Async.EAsync.instMonadExceptOf
- Std.Internal.IO.Async.EAsync.instMonadFinally
- Std.Internal.IO.Async.EAsync.instMonadLiftBaseAsync
- Std.Internal.IO.Async.EAsync.instMonadLiftBaseIO
- Std.Internal.IO.Async.EAsync.instMonadLiftEIO
- Std.Internal.IO.Async.EAsync.instMonadLiftEIO_1
- Std.Internal.IO.Async.EAsync.instOrElse
Creates a new EAsync
out of a RTask
.
Creates an EAsync
computation that immediately returns the given value.
Waits for the result of the EAsync
computation, blocking if necessary.
Equations
- self.wait = do let result ← liftM (Std.Internal.IO.Async.BaseAsync.wait self) match result with | Except.ok a => pure a | Except.error e => EStateM.Result.error e
Lifts an EAsync
computation into an ETask
that can be awaited and joined.
Equations
- x.asTask prio = liftM (Std.Internal.IO.Async.BaseAsync.asTask x prio)
Raises an error of type ε
within the EAsync
monad.
Handles errors in an EAsync
computation by running a handler if one occurs.
Equations
- One or more equations did not get rendered due to their size.
Runs an action, ensuring that some other action always happens afterward.
Equations
- One or more equations did not get rendered due to their size.
Returns the EAsync
computation inside an ETask ε α
, so it can be awaited.
Equations
- self.async prio = Std.Internal.IO.Async.EAsync.lift (self.asTask prio)
Equations
- Std.Internal.IO.Async.EAsync.instFunctor = { map := fun {α β : Type} => Std.Internal.IO.Async.EAsync.map }
Equations
- One or more equations did not get rendered due to their size.
Equations
- Std.Internal.IO.Async.EAsync.instMonadLiftEIO = { monadLift := fun {α : Type} => Std.Internal.IO.Async.EAsync.lift }
Equations
- One or more equations did not get rendered due to their size.
Equations
- One or more equations did not get rendered due to their size.
Equations
- One or more equations did not get rendered due to their size.
Equations
Equations
- One or more equations did not get rendered due to their size.
Equations
- One or more equations did not get rendered due to their size.
Equations
- One or more equations did not get rendered due to their size.
Equations
- One or more equations did not get rendered due to their size.
Equations
- One or more equations did not get rendered due to their size.
Equations
- One or more equations did not get rendered due to their size.
Equations
- One or more equations did not get rendered due to their size.
An asynchronous computation that may produce an error of type IO.Error
..
Equations
This function transforms the operation inside the monad m
into a task and let it run in the background.
Equations
- Std.Internal.IO.Async.background prio = discard ∘ fun (x : m α) => Std.Internal.IO.Async.async x prio
Runs two computations concurrently and returns both results as a pair.
Equations
- One or more equations did not get rendered due to their size.
Runs two computations concurrently and returns the result of the one that finishes first. The other result is lost and the other task is not cancelled, so the task will continue the execution until the end.
Equations
- One or more equations did not get rendered due to their size.
Runs all computations in an Array
concurrently and returns all results as an array.
Equations
- Std.Internal.IO.Async.concurrentlyAll xs prio = do let tasks ← Array.mapM (fun (x : m α) => Std.Internal.IO.Async.async x prio) xs Array.mapM Std.Internal.IO.Async.await tasks
Runs all computations concurrently and returns the result of the first one to finish. All other results are lost, and the tasks are not cancelled, so they'll continue their executing until the end.
Equations
- One or more equations did not get rendered due to their size.