IO

object IO extends IOInstances
Companion
class
trait Sum
trait Mirror
class IOInstances
class IOLowPriorityInstances
class IOParallelNewtype
trait IOCompanionBinaryCompat
trait IOTimerRef
class Object
trait Matchable
class Any

Type members

Inherited classlikes

object Par

Newtype encoding, see the IO.Par type alias for more details.

Newtype encoding, see the IO.Par type alias for more details.

Inherited from
IOParallelNewtype

Inherited types

type MirroredElemLabels <: Tuple

The names of the product elements

The names of the product elements

Inherited from
Mirror
type MirroredLabel <: String

The name of the type

The name of the type

Inherited from
Mirror
type Par[+A] = Type[A]

Newtype encoding for an IO datatype that has a cats.Applicative capable of doing parallel processing in ap and map2, needed for implementing cats.Parallel.

Newtype encoding for an IO datatype that has a cats.Applicative capable of doing parallel processing in ap and map2, needed for implementing cats.Parallel.

Helpers are provided for converting back and forth in Par.apply for wrapping any IO value and Par.unwrap for unwrapping.

The encoding is based on the "newtypes" project by Alexander Konovalov, chosen because it's devoid of boxing issues and a good choice until opaque types will land in Scala.

Inherited from
IOParallelNewtype

Value members

Concrete methods

def apply[A](body: => A): IO[A]

Suspends a synchronous side effect in IO.

Suspends a synchronous side effect in IO.

Alias for IO.delay(body).

def async[A](k: Either[Throwable, A] => Unit => Unit): IO[A]

Suspends an asynchronous side effect in IO.

Suspends an asynchronous side effect in IO.

The given function will be invoked during evaluation of the IO to "schedule" the asynchronous callback, where the callback is the parameter passed to that function. Only the ''first'' invocation of the callback will be effective! All subsequent invocations will be silently dropped.

As a quick example, you can use this function to perform a parallel computation given an ExecutorService:

def fork[A](body: => A)(implicit E: ExecutorService): IO[A] = {
 IO async { cb =>
   E.execute(new Runnable {
     def run() =
       try cb(Right(body)) catch { case NonFatal(t) => cb(Left(t)) }
   })
 }
}

The fork function will do exactly what it sounds like: take a thunk and an ExecutorService and run that thunk on the thread pool. Or rather, it will produce an IO which will do those things when run; it does not schedule the thunk until the resulting IO is run! Note that there is no thread blocking in this implementation; the resulting IO encapsulates the callback in a pure and monadic fashion without using threads.

This function can be thought of as a safer, lexically-constrained version of Promise, where IO is like a safer, lazy version of Future.

See also
def asyncF[A](k: Either[Throwable, A] => Unit => IO[Unit]): IO[A]

Suspends an asynchronous side effect in IO, this being a variant of async that takes a pure registration function.

Suspends an asynchronous side effect in IO, this being a variant of async that takes a pure registration function.

Implements Async.asyncF.

The difference versus async is that this variant can suspend side-effects via the provided function parameter. It's more relevant in polymorphic code making use of the Async type class, as it alleviates the need for Effect.

Contract for the returned IO[Unit] in the provided function:

  • can be asynchronous
  • can be cancelable, in which case it hooks into IO's cancelation mechanism such that the resulting task is cancelable
  • it should not end in error, because the provided callback is the only way to signal the final result and it can only be called once, so invoking it twice would be a contract violation; so on errors thrown in IO, the task can become non-terminating, with the error being printed to stderr
See also
def cancelable[A](k: Either[Throwable, A] => Unit => CancelToken[[A] =>> IO[A]]): IO[A]

Builds a cancelable IO.

Builds a cancelable IO.

Implements Concurrent.cancelable.

The provided function takes a side effectful callback that's supposed to be registered in async apis for signaling a final result.

The provided function also returns an IO[Unit] that represents the cancelation token, the logic needed for canceling the running computations.

Example:

 import java.util.concurrent.ScheduledExecutorService
 import scala.concurrent.duration._

 def sleep(d: FiniteDuration)(implicit ec: ScheduledExecutorService): IO[Unit] =
   IO.cancelable { cb =>
     // Schedules task to run after delay
     val run = new Runnable { def run() = cb(Right(())) }
     val future = ec.schedule(run, d.length, d.unit)

     // Cancellation logic, suspended in IO
     IO(future.cancel(true))
   }

This example is for didactic purposes, you don't need to describe this function, as it's already available in IO.sleep.

See also

async for a simpler variant that builds non-cancelable, async tasks

asyncF for a more potent version that does hook into the underlying cancelation model

def contextShift(ec: ExecutionContext): ContextShift[[A] =>> IO[A]]

Returns a ContextShift instance for IO, built from a Scala ExecutionContext.

Returns a ContextShift instance for IO, built from a Scala ExecutionContext.

NOTE: you don't need to build such instances when using IOApp.

Value Params
ec

is the execution context used for the actual execution of tasks (e.g. bind continuations) and can be backed by the user's own thread-pool

def delay[A](body: => A): IO[A]

Suspends a synchronous side effect in IO.

Suspends a synchronous side effect in IO.

Any exceptions thrown by the effect will be caught and sequenced into the IO.

def eval[A](fa: Eval[A]): IO[A]

Lifts an Eval into IO.

Lifts an Eval into IO.

This function will preserve the evaluation semantics of any actions that are lifted into the pure IO. Eager Eval instances will be converted into thunk-less IO (i.e. eager IO), while lazy eval and memoized will be executed as such.

def fromEither[A](e: Either[Throwable, A]): IO[A]

Lifts an Either[Throwable, A] into the IO[A] context, raising the throwable if it exists.

Lifts an Either[Throwable, A] into the IO[A] context, raising the throwable if it exists.

def fromFuture[A](iof: IO[Future[A]])(cs: ContextShift[[A] =>> IO[A]]): IO[A]

Constructs an IO which evaluates the given Future and produces the result (or failure).

Constructs an IO which evaluates the given Future and produces the result (or failure).

Because Future eagerly evaluates, as well as because it memoizes, this function takes its parameter as an IO, which could be lazily evaluated. If this laziness is appropriately threaded back to the definition site of the Future, it ensures that the computation is fully managed by IO and thus referentially transparent.

Example:

 // Lazy evaluation, equivalent with by-name params
 IO.fromFuture(IO(f))

 // Eager evaluation, for pure futures
 IO.fromFuture(IO.pure(f))

Roughly speaking, the following identities hold:

IO.fromFuture(IO(f)).unsafeToFuture() === f // true-ish (except for memoization)
IO.fromFuture(IO(ioa.unsafeToFuture())) === ioa // true
See also
def fromOption[A](option: Option[A])(orElse: => Throwable): IO[A]

Lifts an Option[A] into the IO[A] context, raising the throwable if the option is empty.

Lifts an Option[A] into the IO[A] context, raising the throwable if the option is empty.

def fromTry[A](t: Try[A]): IO[A]

Lifts an Try[A] into the IO[A] context, raising the throwable if it exists.

Lifts an Try[A] into the IO[A] context, raising the throwable if it exists.

def none[A]: IO[Option[A]]

An IO that contains an empty Option.

An IO that contains an empty Option.

def pure[A](a: A): IO[A]

Suspends a pure value in IO.

Suspends a pure value in IO.

This should ''only'' be used if the value in question has "already" been computed! In other words, something like IO.pure(readLine) is most definitely not the right thing to do! However, IO.pure(42) is correct and will be more efficient (when evaluated) than IO(42), due to avoiding the allocation of extra thunks.

def race[A, B](lh: IO[A], rh: IO[B])(cs: ContextShift[[A] =>> IO[A]]): IO[Either[A, B]]

Run two IO tasks concurrently, and return the first to finish, either in success or error. The loser of the race is canceled.

Run two IO tasks concurrently, and return the first to finish, either in success or error. The loser of the race is canceled.

The two tasks are executed in parallel if asynchronous, the winner being the first that signals a result.

As an example see IO.timeout and IO.timeoutTo

N.B. this is the implementation of Concurrent.race.

Also see racePair for a version that does not cancel the loser automatically on successful results.

Value Params
cs

is an implicit requirement needed because race automatically forks the involved tasks

lh

is the "left" task participating in the race

rh

is the "right" task participating in the race

def racePair[A, B](lh: IO[A], rh: IO[B])(cs: ContextShift[[A] =>> IO[A]]): IO[Either[(A, Fiber[[A] =>> IO[A], B]), (Fiber[[A] =>> IO[A], A], B)]]

Run two IO tasks concurrently, and returns a pair containing both the winner's successful value and the loser represented as a still-unfinished task.

Run two IO tasks concurrently, and returns a pair containing both the winner's successful value and the loser represented as a still-unfinished task.

If the first task completes in error, then the result will complete in error, the other task being canceled.

On usage the user has the option of canceling the losing task, this being equivalent with plain race:

 val ioA: IO[A] = ???
 val ioB: IO[B] = ???

 IO.racePair(ioA, ioB).flatMap {
   case Left((a, fiberB)) =>
     fiberB.cancel.map(_ => a)
   case Right((fiberA, b)) =>
     fiberA.cancel.map(_ => b)
 }

N.B. this is the implementation of Concurrent.racePair.

See race for a simpler version that cancels the loser immediately.

Value Params
cs

is an implicit requirement needed because race automatically forks the involved tasks

lh

is the "left" task participating in the race

rh

is the "right" task participating in the race

def raiseError[A](e: Throwable): IO[A]

Constructs an IO which sequences the specified exception.

Constructs an IO which sequences the specified exception.

If this IO is run using unsafeRunSync or unsafeRunTimed, the exception will be thrown. This exception can be "caught" (or rather, materialized into value-space) using the attempt method.

See also
def raiseUnless(cond: Boolean)(e: => Throwable): IO[Unit]

Returns raiseError when cond is false, otherwise IO.unit

Returns raiseError when cond is false, otherwise IO.unit

Example
val tooMany = 5
val x: Int = ???
IO.raiseUnless(x < tooMany)(new IllegalArgumentException("Too many"))
def raiseWhen(cond: Boolean)(e: => Throwable): IO[Unit]

Returns raiseError when the cond is true, otherwise IO.unit

Returns raiseError when the cond is true, otherwise IO.unit

Example
val tooMany = 5
val x: Int = ???
IO.raiseWhen(x >= tooMany)(new IllegalArgumentException("Too many"))
def shift(cs: ContextShift[[A] =>> IO[A]]): IO[Unit]

Asynchronous boundary described as an effectful IO, managed by the provided ContextShift.

Asynchronous boundary described as an effectful IO, managed by the provided ContextShift.

Note there are 2 overloads of the IO.shift function:

   - One that takes a `ContextShift` that manages the
     thread-pool used to trigger async boundaries.
   - Another that takes a Scala `ExecutionContext` as the
     thread-pool.

   Please use the former by default and use the latter
   only for fine-grained control over the thread pool in
   use.

   By default, Cats Effect can provide instance of
   `ContextShift[IO]` that manages thread-pools, but
   only if there’s an `ExecutionContext` in scope or
   if `IOApp` is used:
         import cats.effect.{IO, ContextShift}

         val ec = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(...))
         val contextShift = IO.contextShift(ec)
   For example we can introduce an asynchronous
   boundary in the `flatMap` chain before a certain task:
         val task = IO(println("task"))

         IO.shift(contextShift).flatMap(_ => task)
   Note that the ContextShift value is taken implicitly
   from the context so you can just do this:
         IO.shift.flatMap(_ => task)
   Or using Cats syntax:
         import cats.syntax.apply._

         IO.shift *> task
         // equivalent to
         ContextShift[IO].shift *> task
   Or we can specify an asynchronous boundary ''after'' the
   evaluation of a certain task:
         task.flatMap(a => IO.shift.map(_ => a))
   Or using Cats syntax:
         task <* IO.shift
         // equivalent to
        task <* ContextShift[IO].shift
   Example of where this might be useful:
       for {
         _ <- IO.shift(BlockingIO)
         bytes <- readFileUsingJavaIO(file)
         _ <- IO.shift(DefaultPool)

         secure = encrypt(bytes, KeyManager)
         _ <- sendResponse(Protocol.v1, secure)

         _ <- IO { println("it worked!") }
       } yield ()
   In the above, `readFileUsingJavaIO` will be shifted to the
   pool represented by `BlockingIO`, so long as it is defined
   using `apply` or `suspend` (which, judging by the name, it
   probably is).  Once its computation is complete, the rest
   of the `for`-comprehension is shifted ''again'', this time
   onto the `DefaultPool`.  This pool is used to compute the
   encrypted version of the bytes, which are then passed to
   `sendResponse`.  If we assume that `sendResponse` is
   defined using `async` (perhaps backed by an NIO socket
   channel), then we don't actually know on which pool the
   final `IO` action (the `println`) will be run.  If we
   wanted to ensure that the `println` runs on `DefaultPool`,
   we would insert another `shift` following `sendResponse`.

   Another somewhat less common application of `shift` is to
   reset the thread stack and yield control back to the
   underlying pool. For example:
       lazy val repeat: IO[Unit] = for {
         _ <- doStuff
         _ <- IO.shift
         _ <- repeat
       } yield ()
   In this example, `repeat` is a very long running `IO`
   (infinite, in fact!) which will just hog the underlying
   thread resource for as long as it continues running.  This
   can be a bit of a problem, and so we inject the `IO.shift`
   which yields control back to the underlying thread pool,
   giving it a chance to reschedule things and provide better
   fairness.  This shifting also "bounces" the thread stack,
   popping all the way back to the thread pool and effectively
   trampolining the remainder of the computation.  This sort
   of manual trampolining is unnecessary if `doStuff` is
   defined using `suspend` or `apply`, but if it was defined
   using `async` and does ''not'' involve any real
   concurrency, the call to `shift` will be necessary to avoid
   a `StackOverflowError`.

   Thus, this function has four important use cases:

    - shifting blocking actions off of the main compute pool,
    - defensively re-shifting asynchronous continuations back
      to the main compute pool
    - yielding control to some underlying pool for fairness
      reasons, and
    - preventing an overflow of the call stack in the case of
      improperly constructed `async` actions

    Note there are 2 overloads of this function:

    - one that takes an [[Timer]] ([[IO.shift(implicit* link]])
    - one that takes a Scala `ExecutionContext` ([[IO.shift(ec* link]])

    Use the former by default, use the later for fine grained
    control over the thread pool used.
Value Params
cs

is the ContextShift that's managing the thread-pool used to trigger this async boundary

def shift(ec: ExecutionContext): IO[Unit]

Asynchronous boundary described as an effectful IO, managed by the provided Scala ExecutionContext.

Asynchronous boundary described as an effectful IO, managed by the provided Scala ExecutionContext.

Note there are 2 overloads of the IO.shift function:

   - One that takes a `ContextShift` that manages the
     thread-pool used to trigger async boundaries.
   - Another that takes a Scala `ExecutionContext` as the
     thread-pool.

   Please use the former by default and use the latter
   only for fine-grained control over the thread pool in
   use.

   By default, Cats Effect can provide instance of
   `ContextShift[IO]` that manages thread-pools, but
   only if there’s an `ExecutionContext` in scope or
   if `IOApp` is used:
         import cats.effect.{IO, ContextShift}

         val ec = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(...))
         val contextShift = IO.contextShift(ec)
   For example we can introduce an asynchronous
   boundary in the `flatMap` chain before a certain task:
         val task = IO(println("task"))

         IO.shift(contextShift).flatMap(_ => task)
   Note that the ContextShift value is taken implicitly
   from the context so you can just do this:
         IO.shift.flatMap(_ => task)
   Or using Cats syntax:
         import cats.syntax.apply._

         IO.shift *> task
         // equivalent to
         ContextShift[IO].shift *> task
   Or we can specify an asynchronous boundary ''after'' the
   evaluation of a certain task:
         task.flatMap(a => IO.shift.map(_ => a))
   Or using Cats syntax:
         task <* IO.shift
         // equivalent to
        task <* ContextShift[IO].shift
   Example of where this might be useful:
       for {
         _ <- IO.shift(BlockingIO)
         bytes <- readFileUsingJavaIO(file)
         _ <- IO.shift(DefaultPool)

         secure = encrypt(bytes, KeyManager)
         _ <- sendResponse(Protocol.v1, secure)

         _ <- IO { println("it worked!") }
       } yield ()
   In the above, `readFileUsingJavaIO` will be shifted to the
   pool represented by `BlockingIO`, so long as it is defined
   using `apply` or `suspend` (which, judging by the name, it
   probably is).  Once its computation is complete, the rest
   of the `for`-comprehension is shifted ''again'', this time
   onto the `DefaultPool`.  This pool is used to compute the
   encrypted version of the bytes, which are then passed to
   `sendResponse`.  If we assume that `sendResponse` is
   defined using `async` (perhaps backed by an NIO socket
   channel), then we don't actually know on which pool the
   final `IO` action (the `println`) will be run.  If we
   wanted to ensure that the `println` runs on `DefaultPool`,
   we would insert another `shift` following `sendResponse`.

   Another somewhat less common application of `shift` is to
   reset the thread stack and yield control back to the
   underlying pool. For example:
       lazy val repeat: IO[Unit] = for {
         _ <- doStuff
         _ <- IO.shift
         _ <- repeat
       } yield ()
   In this example, `repeat` is a very long running `IO`
   (infinite, in fact!) which will just hog the underlying
   thread resource for as long as it continues running.  This
   can be a bit of a problem, and so we inject the `IO.shift`
   which yields control back to the underlying thread pool,
   giving it a chance to reschedule things and provide better
   fairness.  This shifting also "bounces" the thread stack,
   popping all the way back to the thread pool and effectively
   trampolining the remainder of the computation.  This sort
   of manual trampolining is unnecessary if `doStuff` is
   defined using `suspend` or `apply`, but if it was defined
   using `async` and does ''not'' involve any real
   concurrency, the call to `shift` will be necessary to avoid
   a `StackOverflowError`.

   Thus, this function has four important use cases:

    - shifting blocking actions off of the main compute pool,
    - defensively re-shifting asynchronous continuations back
      to the main compute pool
    - yielding control to some underlying pool for fairness
      reasons, and
    - preventing an overflow of the call stack in the case of
      improperly constructed `async` actions

    Note there are 2 overloads of this function:

    - one that takes an [[Timer]] ([[IO.shift(implicit* link]])
    - one that takes a Scala `ExecutionContext` ([[IO.shift(ec* link]])

    Use the former by default, use the later for fine grained
    control over the thread pool used.
Value Params
ec

is the Scala ExecutionContext that's managing the thread-pool used to trigger this async boundary

def sleep(duration: FiniteDuration)(timer: Timer[[A] =>> IO[A]]): IO[Unit]

Creates an asynchronous task that on evaluation sleeps for the specified duration, emitting a notification on completion.

Creates an asynchronous task that on evaluation sleeps for the specified duration, emitting a notification on completion.

This is the pure, non-blocking equivalent to:

  • Thread.sleep (JVM)
  • ScheduledExecutorService.schedule (JVM)
  • setTimeout (JavaScript)

Similar with IO.shift, you can combine it via flatMap to create delayed tasks:

 val timeout = IO.sleep(10.seconds).flatMap { _ =>
   IO.raiseError(new TimeoutException)
 }

This operation creates an asynchronous boundary, even if the specified duration is zero, so you can count on this equivalence:

 IO.sleep(Duration.Zero) <-> IO.shift

The created task is cancelable and so it can be used safely in race conditions without resource leakage.

Value Params
duration

is the time span to wait before emitting the tick

timer

is the Timer used to manage this delayed task, IO.sleep being in fact just an alias for Timer.sleep

Returns

a new asynchronous and cancelable IO that will sleep for the specified duration and then finally emit a tick

def suspend[A](thunk: => IO[A]): IO[A]

Suspends a synchronous side effect which produces an IO in IO.

Suspends a synchronous side effect which produces an IO in IO.

This is useful for trampolining (i.e. when the side effect is conceptually the allocation of a stack frame). Any exceptions thrown by the side effect will be caught and sequenced into the IO.

def unlessA(cond: Boolean)(action: => IO[Unit]): IO[Unit]

Returns the given argument if cond is false, otherwise IO.Unit

Returns the given argument if cond is false, otherwise IO.Unit

See also

IO.whenA for the inverse

IO.raiseWhen for conditionally raising an error

def whenA(cond: Boolean)(action: => IO[Unit]): IO[Unit]

Returns the given argument if cond is true, otherwise IO.Unit

Returns the given argument if cond is true, otherwise IO.Unit

See also

IO.unlessA for the inverse

IO.raiseWhen for conditionally raising an error

Inherited methods

def timer(ec: ExecutionContext): Timer[[A] =>> IO[A]]

Returns a Timer instance for IO.

Returns a Timer instance for IO.

Value Params
ec

is an execution context that gets used for evaluating the sleep tick

Inherited from
IOTimerRef
def timer: Timer[[A] =>> IO[A]]

Returns a reusable Timer instance for IO.

Returns a reusable Timer instance for IO.

Inherited from
IOTimerRef

Concrete fields

val cancelBoundary: IO[Unit]

Returns a cancelable boundary — an IO task that checks for the cancellation status of the run-loop and does not allow for the bind continuation to keep executing in case cancellation happened.

Returns a cancelable boundary — an IO task that checks for the cancellation status of the run-loop and does not allow for the bind continuation to keep executing in case cancellation happened.

This operation is very similar to IO.shift, as it can be dropped in flatMap chains in order to make loops cancelable.

Example:

def fib(n: Int, a: Long, b: Long): IO[Long] =
  IO.suspend {
    if (n <= 0) IO.pure(a) else {
      val next = fib(n - 1, b, a + b)

      // Every 100-th cycle, check cancellation status
      if (n % 100 == 0)
        IO.cancelBoundary *> next
      else
        next
    }
  }
val never: IO[Nothing]

A non-terminating IO, alias for async(_ => ()).

A non-terminating IO, alias for async(_ => ()).

Returns the accumulated trace of the currently active fiber.

Returns the accumulated trace of the currently active fiber.

val unit: IO[Unit]

Alias for IO.pure(()).

Alias for IO.pure(()).

Implicits

Inherited implicits

implicit val ioAlign: Align[[A] =>> IO[A]]
Inherited from
IOInstances
implicit def ioConcurrentEffect(cs: ContextShift[[A] =>> IO[A]]): ConcurrentEffect[[A] =>> IO[A]]
Inherited from
IOInstances
implicit val ioEffect: Effect[[A] =>> IO[A]]
Inherited from
IOLowPriorityInstances
implicit def ioMonoid[A](`evidence$1`: Monoid[A]): Monoid[IO[A]]
Inherited from
IOInstances
implicit def ioParallel(cs: ContextShift[[A] =>> IO[A]]): Aux[[A] =>> IO[A], Par]
Inherited from
IOInstances
implicit def ioSemigroup[A](`evidence$3`: Semigroup[A]): Semigroup[IO[A]]
Inherited from
IOLowPriorityInstances
implicit val ioSemigroupK: SemigroupK[[A] =>> IO[A]]
Inherited from
IOInstances
implicit def parAlign(cs: ContextShift[[A] =>> IO[A]]): Align[Par]
Inherited from
IOInstances
implicit def parApplicative(cs: ContextShift[[A] =>> IO[A]]): Applicative[Par]
Inherited from
IOLowPriorityInstances
implicit def parCommutativeApplicative(cs: ContextShift[[A] =>> IO[A]]): CommutativeApplicative[Par]
Inherited from
IOInstances