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
Represents monads that can launch computations asynchronously of type t
in a monad m
.
Starts an asynchronous computation in another monad.
Instances
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 α
Instances For
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
Instances For
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
Instances For
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.
Instances For
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.
Instances For
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
Instances For
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.
Instances For
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
Instances For
Create a new AsyncTask
that will run after x
has finished.
If x
:
- errors, return an
AsyncTask
that resolves to the error. - succeeds, return an
AsyncTask
that resolves tof x
.
Equations
Instances For
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
Instances For
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.
Instances For
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
Instances For
Create an AsyncTask
that resolves to the value of x
.
Equations
Instances For
A MaybeTask α
represents a computation that either:
- Is immediately available as an
α
value, or - Is an asynchronous computation that will eventually produce an
α
value.
Instances For
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
Instances For
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)
Instances For
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)
Instances For
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
Creates a BaseAsync
computation that immediately returns the given value.
Equations
Instances For
Maps the result of a BaseAsync
computation with a function.
Equations
- One or more equations did not get rendered due to their size.
Instances For
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
Instances For
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
Instances For
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)
Instances For
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)
Instances For
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
Equations
Instances For
Creates an EAsync
computation that immediately returns the given value.
Equations
Instances For
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
Instances For
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)
Instances For
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.
Instances For
Runs an action, ensuring that some other action always happens afterward.
Equations
- One or more equations did not get rendered due to their size.
Instances For
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)
Instances For
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.
Instances For
An asynchronous computation that may produce an error of type IO.Error
..
Equations
Instances For
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
Instances For
Runs two computations concurrently and returns both results as a pair.
Equations
- One or more equations did not get rendered due to their size.
Instances For
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.
Instances For
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
Instances For
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.