Packages

object IO extends IOInstances

Source
IO.scala
Linear Supertypes
IOInstances, IOLowPriorityInstances, IOParallelNewtype, IOCompanionBinaryCompat, IOTimerRef, AnyRef, Any
Ordering
  1. Alphabetic
  2. By Inheritance
Inherited
  1. IO
  2. IOInstances
  3. IOLowPriorityInstances
  4. IOParallelNewtype
  5. IOCompanionBinaryCompat
  6. IOTimerRef
  7. AnyRef
  8. Any
  1. Hide All
  2. Show All
Visibility
  1. Public
  2. All

Type Members

  1. type Par[+A] = IOParallelNewtype.Par.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.

    Definition Classes
    IOParallelNewtype

Value Members

  1. final def !=(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  2. final def ##(): Int
    Definition Classes
    AnyRef → Any
  3. final def ==(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  4. def apply[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.

  5. final def asInstanceOf[T0]: T0
    Definition Classes
    Any
  6. 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.

  7. 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
        }
      }
  8. def cancelable[A](k: ((Either[Throwable, A]) ⇒ Unit) ⇒ IO[Unit]): IO[A]

    Builds a cancelable IO.

  9. def clone(): AnyRef
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @native() @throws( ... )
  10. final def eq(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  11. def equals(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  12. 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.

  13. def finalize(): Unit
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( classOf[java.lang.Throwable] )
  14. 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.

  15. def fromFuture[A](iof: IO[Future[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

    IO#unsafeToFuture

  16. final def getClass(): Class[_]
    Definition Classes
    AnyRef → Any
    Annotations
    @native()
  17. def hashCode(): Int
    Definition Classes
    AnyRef → Any
    Annotations
    @native()
  18. implicit val ioConcurrentEffect: ConcurrentEffect[IO]
    Definition Classes
    IOInstances
  19. implicit def ioMonoid[A](implicit arg0: Monoid[A]): Monoid[IO[A]]
    Definition Classes
    IOInstances
  20. implicit val ioParallel: Parallel[IO, Par]
    Definition Classes
    IOInstances
  21. implicit def ioSemigroup[A](implicit arg0: Semigroup[A]): Semigroup[IO[A]]
    Definition Classes
    IOLowPriorityInstances
  22. implicit val ioSemigroupK: SemigroupK[IO]
    Definition Classes
    IOInstances
  23. final def isInstanceOf[T0]: Boolean
    Definition Classes
    Any
  24. final def ne(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  25. val never: IO[Nothing]

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

  26. final def notify(): Unit
    Definition Classes
    AnyRef
    Annotations
    @native()
  27. final def notifyAll(): Unit
    Definition Classes
    AnyRef
    Annotations
    @native()
  28. implicit val parApplicative: Applicative[Par]
    Definition Classes
    IOInstances
  29. 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.

  30. def race[A, B](lh: IO[A], rh: IO[B]): IO[Either[A, B]]

    Run two IO tasks concurrently, and return the first to finish, either in success or error.

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

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

    As an example, this is how a timeout operation could be implemented in terms of race:

    import cats.effect._
    import scala.concurrent.duration._
    
    def timeoutTo[A](io: IO[A], after: FiniteDuration, fallback: IO[A])
      (implicit timer: Timer[IO]): IO[A] = {
    
      IO.race(io, timer.sleep(timer)).flatMap {
        case Left((a, _)) => IO.pure(a)
        case Right((_, _)) => fallback
      }
    }
    
    def timeout[A](io: IO[A], after: FiniteDuration)
      (implicit timer: Timer[IO]): IO[A] = {
    
      timeoutTo(io, after,
        IO.raiseError(new TimeoutException(after.toString)))
    }

    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.

  31. def racePair[A, B](lh: IO[A], rh: IO[B]): IO[Either[(A, Fiber[IO, B]), (Fiber[IO, 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 cancelled.

    On usage the user has the option of cancelling 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.

  32. 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

    IO#attempt

  33. 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.

    This operation can be used in flatMap chains to "shift" the continuation of the run-loop to another thread or call stack.

    For example we can introduce an asynchronous boundary in the flatMap chain before a certain task:

    IO.shift.flatMap(_ => task)

    Or using Cats syntax:

    import cats.syntax.all._
    
    Task.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

    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 (link)
    • one that takes a Scala ExecutionContext (link)

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

    ec

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

  34. def shift(implicit timer: Timer[IO]): IO[Unit]

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

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

    This operation can be used in flatMap chains to "shift" the continuation of the run-loop to another thread or call stack.

    For example we can introduce an asynchronous boundary in the flatMap chain before a certain task:

    IO.shift.flatMap(_ => task)

    Or using Cats syntax:

    import cats.syntax.all._
    
    Task.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

    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 (link)
    • one that takes a Scala ExecutionContext (link)

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

    timer

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

  35. def sleep(duration: FiniteDuration)(implicit timer: Timer[IO]): 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.

    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

  36. 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.

  37. final def synchronized[T0](arg0: ⇒ T0): T0
    Definition Classes
    AnyRef
  38. def timer(ec: ExecutionContext, sc: ScheduledExecutorService): Timer[IO]

    Returns a Timer instance for IO, built from a Scala ExecutionContext and a Java ScheduledExecutorService.

    Returns a Timer instance for IO, built from a Scala ExecutionContext and a Java ScheduledExecutorService.

    N.B. this is the JVM-specific version. On top of JavaScript the implementation needs no ExecutionContext.

    ec

    is the execution context used for actual execution tasks (e.g. bind continuations)

    sc

    is the ScheduledExecutorService used for scheduling ticks with a delay

    Definition Classes
    IOTimerRef
  39. implicit def timer(implicit ec: ExecutionContext): Timer[IO]

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

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

    N.B. this is the JVM-specific version. On top of JavaScript the implementation needs no ExecutionContext.

    ec

    is the execution context used for actual execution tasks (e.g. bind continuations)

    Definition Classes
    IOTimerRef
  40. def toString(): String
    Definition Classes
    AnyRef → Any
  41. val unit: IO[Unit]

    Alias for IO.pure(()).

  42. final def wait(): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  43. final def wait(arg0: Long, arg1: Int): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  44. final def wait(arg0: Long): Unit
    Definition Classes
    AnyRef
    Annotations
    @native() @throws( ... )
  45. object Par extends IONewtype

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

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

    Definition Classes
    IOParallelNewtype

Inherited from IOInstances

Inherited from IOLowPriorityInstances

Inherited from IOParallelNewtype

Inherited from IOCompanionBinaryCompat

Inherited from IOTimerRef

Inherited from AnyRef

Inherited from Any

Ungrouped