Materializes any sequenced exceptions into value space, where they may be handled.
Materializes any sequenced exceptions into value space, where they may be handled.
This is analogous to the catch
clause in try
/catch
, being
the inverse of IO.raiseError
. Thus:
IO.raiseError(ex).attempt.unsafeRunAsync === Left(ex)
Sequences the specified IO
ensuring evaluation regardless of
whether or not the target IO
raises an exception.
Sequences the specified IO
ensuring evaluation regardless of
whether or not the target IO
raises an exception.
Analogous to finally
in a try
/catch
/finally
block. If an
exception is raised by the finalizer, it will be passed sequenced
into the resultant. This is true even if the target also
raised an exception. It mirrors the semantics of try
/finally
on the JVM when you perform similar operations.
Example:
try throw e1 finally throw e2 // throws e2 IO.raiseError(e1).ensuring(IO.raiseError(e2)) === IO.raiseError(e2)
This function is distinct from monadic flatMap
(well, really
applicative apply2
) in that an exception sequenced into a
monadic bind chain will short-circuit the chain and the
subsequent actions will not be run.
Monadic bind on IO
, used for sequentially composing two IO
actions, where the value produced by the first IO
is passed as
input to a function producing the second IO
action.
Monadic bind on IO
, used for sequentially composing two IO
actions, where the value produced by the first IO
is passed as
input to a function producing the second IO
action.
Due to this operation's signature, flatMap
forces a data
dependency between two IO
actions, thus ensuring sequencing
(e.g. one action to be executed before another one).
Any exceptions thrown within the function will be caught and
sequenced into the IO
, because due to the nature of
asynchronous processes, without catching and handling exceptions,
failures would be completely silent and IO
references would
never terminate on evaluation.
Functor map on IO
.
Functor map on IO
. Given a mapping functions, it transforms the
value produced by the source, while keeping the IO
context.
Any exceptions thrown within the function will be caught and
sequenced into the IO
, because due to the nature of
asynchronous processes, without catching and handling exceptions,
failures would be completely silent and IO
references would
never terminate on evaluation.
Produces an IO
reference that is guaranteed to be safe to run
synchronously (i.e.
Produces an IO
reference that is guaranteed to be safe to run
synchronously (i.e. unsafeRunSync), being the safe analogue
to unsafeRunAsync.
This operation is isomorphic to unsafeRunAsync. What it does
is to let you describe asynchronous execution with a function
that stores off the results of the original IO
as a
side effect, thus avoiding the usage of impure callbacks or
eager evaluation.
Shifts the synchronous prefixes and continuation of the IO
onto
the specified thread pool.
Shifts the synchronous prefixes and continuation of the IO
onto
the specified thread pool.
Asynchronous actions cannot be shifted, since they are scheduled rather than run. Also, no effort is made to re-shift synchronous actions which *follow* asynchronous actions within a bind chain; those actions will remain on the continuation thread inherited from their preceding async action. Critically though, synchronous actions which are bound after the results of this function will also be shifted onto the pool specified here. Thus, you can think of this function as shifting *before* (the contiguous synchronous prefix) and after (any continuation of the result).
There are two immediately obvious applications to this function.
One is to re-shift async actions back to a "main" thread pool.
For example, if you create an async action to wrap around some
sort of event listener, you probably want to shift
it
immediately to take the continuation off of the event dispatch
thread. Another use-case is to ensure that a blocking
synchronous action is taken *off* of the main CPU-bound pool. A
common example here would be any use of the java.io
package,
which is entirely blocking and should never be run on your main
CPU-bound pool.
Note that this function is idempotent given equal values of EC
,
but only prefix-idempotent given differing EC
values. For
example:
val fioa = IO { File.createTempFile("fubar") } fioa.shift(BlockingIOPool).shift(MainPool)
The inner call to shift
will force the synchronous prefix of
fioa
(which is just the single action) to execute on the
BlockingIOPool
when the IO
is run, and also ensures that the
continuation of this action remains on the BlockingIOPool
. The
outer shift
similarly forces the synchronous prefix of the
results of the inner shift
onto the specified pool
(MainPool
), but the results of shift
have no synchronous
prefix, meaning that the "before" part of the outer shift
is a
no-op. The "after" part is not, however, and will force the
continuation of the resulting IO
back onto the MainPool
.
Which is exactly what you want most of the time with blocking
actions of this type.
Passes the result of the encapsulated effects to the given callback by running them as impure side effects.
Passes the result of the encapsulated effects to the given callback by running them as impure side effects.
Any exceptions raised within the effect will be passed to the
callback in the Either
. The callback will be invoked at most
*once*. Note that it is very possible to construct an IO which
never returns while still never blocking a thread, and attempting
to evaluate that IO with this method will result in a situation
where the callback is *never* invoked.
As the name says, this is an UNSAFE function as it is impure and performs side effects. You should ideally only call this function once, at the very end of your program.
Produces the result by running the encapsulated effects as impure side effects.
Produces the result by running the encapsulated effects as impure side effects.
If any component of the computation is asynchronous, the current
thread will block awaiting the results of the async computation.
On JavaScript, an exception will be thrown instead to avoid
generating a deadlock. By default, this blocking will be
unbounded. To limit the thread block to some fixed time, use
unsafeRunTimed
instead.
Any exceptions raised within the effect will be re-thrown during evaluation.
As the name says, this is an UNSAFE function as it is impure and performs side effects, not to mention blocking, throwing exceptions, and doing other things that are at odds with reasonable software. You should ideally only call this function *once*, at the very end of your program.
Similar to unsafeRunSync
, except with a bounded blocking
duration when awaiting asynchronous results.
Similar to unsafeRunSync
, except with a bounded blocking
duration when awaiting asynchronous results.
Please note that the limit
parameter does not limit the time of
the total computation, but rather acts as an upper bound on any
*individual* asynchronous block. Thus, if you pass a limit of 5
seconds
to an IO
consisting solely of synchronous actions, the
evaluation may take considerably longer than 5 seconds!
Furthermore, if you pass a limit of 5 seconds
to an IO
consisting of several asynchronous actions joined together,
evaluation may take up to n * 5 seconds
, where n
is the
number of joined async actions.
As soon as an async blocking limit is hit, evaluation
immediately aborts and None
is returned.
Please note that this function is intended for testing; it should never appear in your mainline production code! It is absolutely not an appropriate function to use if you want to implement timeouts, or anything similar. If you need that sort of functionality, you should be using a streaming library (like fs2 or Monix).
Evaluates the effect and produces the result in a Future
.
Evaluates the effect and produces the result in a Future
.
This is similar to unsafeRunAsync
in that it evaluates the IO
as a side effect in a non-blocking fashion, but uses a Future
rather than an explicit callback. This function should really
only be used if interoperating with legacy code which uses Scala
futures.
A pure abstraction representing the intention to perform a side effect, where the result of that side effect may be obtained synchronously (via return) or asynchronously (via callback).
Effects contained within this abstraction are not evaluated until the "end of the world", which is to say, when one of the "unsafe" methods are used. Effectful results are not memoized, meaning that memory overhead is minimal (and no leaks), and also that a single effect may be run multiple times in a referentially-transparent manner. For example:
The above will print "hey!" twice, as the effect will be re-run each time it is sequenced in the monadic chain.
IO
is trampolined for all synchronous joins. This means that you can safely callflatMap
in a recursive function of arbitrary depth, without fear of blowing the stack. However,IO
cannot guarantee stack-safety in the presence of arbitrarily nested asynchronous suspensions. This is quite simply because it is impossible (on the JVM) to guarantee stack-safety in that case. For example:This should blow the stack when evaluated. Also note that there is no way to encode this using
tailRecM
in such a way that it does not blow the stack. Thus, thetailRecM
onMonad[IO]
is not guaranteed to produce anIO
which is stack-safe when run, but will rather make every attempt to do so barring pathological structure.IO
makes no attempt to control finalization or guaranteed resource-safety in the presence of concurrent preemption, simply becauseIO
does not care about concurrent preemption at all!IO
actions are not interruptible and should be considered broadly-speaking atomic, at least when used purely.