IO

cats.effect.IO$
See theIO companion class
object IO

Attributes

Companion:
class
Source:
IO.scala
Graph
Supertypes
trait Sum
trait Mirror
class Object
trait Matchable
class Any
Self type
IO.type

Members list

Concise view

Type members

Inherited classlikes

protected class IOSemigroup[A](implicit val A: Semigroup[A]) extends Semigroup[IO[A]]

Attributes

Inherited from:
IOLowPriorityImplicits (hidden)
Source:
IO.scala
Graph
Supertypes
trait Semigroup[IO[A]]
trait Serializable
class Object
trait Matchable
class Any

Types

type Par[A] = T[IO, 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.

For converting back and forth you can use either the Parallel[IO] instance or the methods cats.effect.kernel.Par.ParallelF.apply for wrapping any IO value and cats.effect.kernel.Par.ParallelF.value for unwrapping it.

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.

Attributes

Source:
IO.scala

Inherited types

type MirroredElemLabels <: Tuple

The names of the product elements

The names of the product elements

Attributes

Inherited from:
Mirror
Source:
Mirror.scala

The name of the type

The name of the type

Attributes

Inherited from:
Mirror
Source:
Mirror.scala

Value members

Concrete methods

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

Suspends a synchronous side effect in IO. Use IO.apply if your side effect is not thread-blocking; otherwise you should use IO.blocking (uncancelable) or IO.interruptible (cancelable).

Suspends a synchronous side effect in IO. Use IO.apply if your side effect is not thread-blocking; otherwise you should use IO.blocking (uncancelable) or IO.interruptible (cancelable).

Alias for IO.delay.

Attributes

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

Suspends an asynchronous side effect in IO.

Suspends an asynchronous side effect in IO.

The given function k will be invoked during evaluation of the IO to "schedule" the asynchronous callback, where the callback of type Either[Throwable, A] => Unit is the parameter passed to that function. Only the ''first'' invocation of the callback will be effective! All subsequent invocations will be silently dropped.

The process of registering the callback itself is suspended in IO (the outer IO of IO[Option[IO[Unit]]]).

The effect returns Option[IO[Unit]] which is an optional finalizer to be run in the event that the fiber running async(k) is canceled.

For example, here is a simplified version of IO.fromCompletableFuture:

def fromCompletableFuture[A](fut: IO[CompletableFuture[A]]): IO[A] = {
 fut.flatMap { cf =>
   IO.async { cb =>
     IO {
       //Invoke the callback with the result of the completable future
       val stage = cf.handle[Unit] {
         case (a, null) => cb(Right(a))
         case (_, e) => cb(Left(e))
       }

       //Cancel the completable future if the fiber is canceled
       Some(IO(stage.cancel(false)).void)
     }
   }
 }
}

Note that async is uncancelable during its registration.

Attributes

See also:

async_ for a simplified variant without a finalizer

asyncCheckAttempt for more generic version providing an optional immediate result of computation

Source:
IO.scala
def asyncCheckAttempt[A](k: (Either[Throwable, A] => Unit) => IO[Either[Option[IO[Unit]], A]]): IO[A]

Suspends an asynchronous side effect with optional immediate result in IO.

Suspends an asynchronous side effect with optional immediate result in IO.

The given function k will be invoked during evaluation of the IO to:

  • check if result is already available;
  • "schedule" the asynchronous callback, where the callback of type Either[Throwable, A] \=> Unit is the parameter passed to that function. Only the ''first'' invocation of the callback will be effective! All subsequent invocations will be silently dropped.

The process of registering the callback itself is suspended in IO (the outer IO of IO[Either[Option[IO[Unit]], A]]).

The effect returns Either[Option[IO[Unit]], A] where:

  • right side A is an immediate result of computation (callback invocation will be dropped);
  • left side Option[IO[Unit]]is an optional finalizer to be run in the event that the fiber running asyncCheckAttempt(k) is canceled.

For example, here is a simplified version of IO.fromCompletableFuture:

def fromCompletableFuture[A](fut: IO[CompletableFuture[A]]): IO[A] = {
 fut.flatMap { cf =>
   IO.asyncCheckAttempt { cb =>
     if (cf.isDone) {
       //Register immediately available result of the completable future or handle an error
       IO(cf.get)
         .map(Right(_))
         .handleError { e =>
           cb(Left(e))
           Left(None)
         }
     } else {
       IO {
         //Invoke the callback with the result of the completable future
         val stage = cf.handle[Unit] {
           case (a, null) => cb(Right(a))
           case (_, e) => cb(Left(e))
         }

         //Cancel the completable future if the fiber is canceled
         Left(Some(IO(stage.cancel(false)).void))
       }
     }
   }
 }
}

Note that asyncCheckAttempt is uncancelable during its registration.

Attributes

See also:

async for a simplified variant without an option for immediate result

Source:
IO.scala
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 k 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, exc: ExecutorService): IO[A] =
 IO async_ { cb =>
   exc.execute(new Runnable {
     def run() =
       try cb(Right(body)) catch { case t if 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.

Also, note that async is uncancelable during its registration.

Attributes

See also:

async for more generic version providing a finalizer

asyncCheckAttempt for more generic version providing an optional immediate result of computation and a finalizer

Source:
IO.scala
def both[A, B](left: IO[A], right: IO[B]): IO[(A, B)]

Attributes

Source:
IO.scala
def bothOutcome[A, B](left: IO[A], right: IO[B]): IO[(OutcomeIO[A], OutcomeIO[B])]

Attributes

Source:
IO.scala
def bracketFull[A, B](acquire: Poll[IO] => IO[A])(use: A => IO[B])(release: (A, OutcomeIO[B]) => IO[Unit]): IO[B]

Attributes

Source:
IO.scala

Attributes

Source:
IO.scala
def cede: IO[Unit]

Introduces a fairness boundary that yields control back to the scheduler of the runtime system. This allows the carrier thread to resume execution of another waiting fiber.

Introduces a fairness boundary that yields control back to the scheduler of the runtime system. This allows the carrier thread to resume execution of another waiting fiber.

This function is primarily useful when performing long-running computation that is outside of the monadic context. For example:

 fa.map(data => expensiveWork(data))

In the above, we're assuming that expensiveWork is a function which is entirely compute-bound but very long-running. A good rule of thumb is to consider a function "expensive" when its runtime is around three or more orders of magnitude higher than the overhead of the map function itself (which runs in around 5 nanoseconds on modern hardware). Thus, any expensiveWork function which requires around 10 microseconds or longer to execute should be considered "long-running".

The danger is that these types of long-running actions outside of the monadic context can result in degraded fairness properties. The solution is to add an explicit cede both before and after the expensive operation:

 (fa <* IO.cede).map(data => expensiveWork(data)).guarantee(IO.cede)

Note that extremely long-running expensiveWork functions can still cause fairness issues, even when used with cede. This problem is somewhat fundamental to the nature of scheduling such computation on carrier threads. Whenever possible, it is best to break apart any such functions into multiple pieces invoked independently (e.g. via chained map calls) whenever the execution time exceeds five or six orders of magnitude beyond the overhead of map itself (around 1 millisecond on most hardware).

This operation is not ''required'' in most applications, particularly those which are primarily I/O bound, as IO itself will automatically introduce fairness boundaries without requiring user input. These automatic boundaries are controlled by the cats.effect.unsafe.IORuntimeConfig.autoYieldThreshold configuration parameter, which in turn may be adjusted by overriding IOApp.runtimeConfig.

Attributes

Source:
IO.scala
def cont[K, R](body: Cont[IO, K, R]): IO[R]

This is a low-level API which is meant for implementors, please use background, start, async, or Deferred instead, depending on the use case

This is a low-level API which is meant for implementors, please use background, start, async, or Deferred instead, depending on the use case

Attributes

Source:
IO.scala
def defer[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.

Attributes

Source:
IO.scala
def deferred[A]: IO[Deferred[IO, A]]

Attributes

Source:
IO.scala
def delay[A](thunk: => A): IO[A]

Suspends a synchronous side effect in IO. Use IO.delay if your side effect is not thread-blocking; otherwise you should use IO.blocking (uncancelable) or IO.interruptible (cancelable).

Suspends a synchronous side effect in IO. Use IO.delay if your side effect is not thread-blocking; otherwise you should use IO.blocking (uncancelable) or IO.interruptible (cancelable).

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

Attributes

Source:
IO.scala
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.

Attributes

Source:
IO.scala
def executor: IO[Executor]

Attributes

Source:
IO.scala
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.

Attributes

Source:
IO.scala
def fromFuture[A](fut: 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

Attributes

See also:
Source:
IO.scala
def fromFutureCancelable[A](fut: IO[(Future[A], IO[Unit])]): IO[A]

Like fromFuture, but is cancelable via the provided finalizer.

Like fromFuture, but is cancelable via the provided finalizer.

Attributes

Source:
IO.scala
def fromOption[A](o: 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.

Attributes

Source:
IO.scala
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.

Attributes

Source:
IO.scala

Attributes

Source:
IO.scala
def never[A]: IO[A]

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

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

Attributes

Source:
IO.scala
def none[A]: IO[Option[A]]

An IO that contains an empty Option.

An IO that contains an empty Option.

Attributes

See also:

some for the non-empty Option variant

Source:
IO.scala
def parReplicateAN[A](n: Int)(replicas: Int, ma: IO[A]): IO[List[A]]

Like Parallel.parReplicateA, but limits the degree of parallelism.

Like Parallel.parReplicateA, but limits the degree of parallelism.

Attributes

Source:
IO.scala
def parSequenceN[T[_] : Traverse, A](n: Int)(tma: T[IO[A]]): IO[T[A]]

Like Parallel.parSequence, but limits the degree of parallelism.

Like Parallel.parSequence, but limits the degree of parallelism.

Attributes

Source:
IO.scala
def parTraverseN[T[_] : Traverse, A, B](n: Int)(ta: T[A])(f: A => IO[B]): IO[T[B]]

Like Parallel.parTraverse, but limits the degree of parallelism.

Like Parallel.parTraverse, but limits the degree of parallelism.

Attributes

Source:
IO.scala
def pollers: IO[List[Any]]

Attributes

Source:
IO.scala
def println[A](a: A)(implicit S: Show[A]): IO[Unit]

Prints a value to the standard output followed by a new line using the implicit cats.Show instance.

Prints a value to the standard output followed by a new line using the implicit cats.Show instance.

Attributes

a

value to be printed to the standard output

See also:

cats.effect.std.Console for more standard input, output and error operations

Source:
IO.scala
def pure[A](value: A): IO[A]

Lifts a pure value into IO.

Lifts a pure value into 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.

Attributes

Source:
IO.scala
def race[A, B](left: IO[A], right: IO[B]): 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, the winner being the first that signals a result.

As an example see IO.timeout and IO.timeoutTo

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

Attributes

left

is the "left" task participating in the race

right

is the "right" task participating in the race

Source:
IO.scala
def racePair[A, B](left: IO[A], right: IO[B]): IO[Either[(OutcomeIO[A], FiberIO[B]), (FiberIO[A], OutcomeIO[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.

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.as(a)
   case Right((fiberA, b)) =>
     fiberA.cancel.as(b)
 }

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

Attributes

left

is the "left" task participating in the race

right

is the "right" task participating in the race

Source:
IO.scala
def raiseError[A](t: 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.

Attributes

See also:
Source:
IO.scala
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

Attributes

Example:
val tooMany = 5
val x: Int = ???
IO.raiseUnless(x < tooMany)(new IllegalArgumentException("Too many"))
Source:
IO.scala
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

Attributes

Example:
val tooMany = 5
val x: Int = ???
IO.raiseWhen(x >= tooMany)(new IllegalArgumentException("Too many"))
Source:
IO.scala
def randomUUID: IO[UUID]

Attributes

Returns:

a randomly-generated UUID This is equivalent to UUIDGen[IO].randomUUID, just provided as a method for convenience

Source:
IO.scala

Attributes

Source:
IO.scala
def ref[A](a: A): IO[Ref[IO, A]]

Attributes

Source:
IO.scala
def sleep(delay: Duration): 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)

You can combine it with flatMap to create delayed tasks:

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

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

Attributes

delay

the time span to wait before emitting the tick

Returns:

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

Source:
IO.scala
def sleep(finiteDelay: FiniteDuration): IO[Unit]

Attributes

Source:
IO.scala
def some[A](a: A): IO[Option[A]]

An IO that contains some Option of the given value.

An IO that contains some Option of the given value.

Attributes

See also:

none for the empty Option variant

Source:
IO.scala
def stub: IO[Nothing]

Attributes

Source:
IO.scala
def trace: IO[Trace]

Attributes

Source:
IO.scala
def uncancelable[A](body: Poll[IO] => IO[A]): IO[A]

Attributes

Source:
IO.scala

Attributes

Source:
IO.scala
def unit: IO[Unit]

Alias for IO.pure(()).

Alias for IO.pure(()).

Attributes

Source:
IO.scala
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

Attributes

See also:

IO.whenA for the inverse

IO.raiseWhen for conditionally raising an error

Source:
IO.scala
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

Attributes

See also:

IO.unlessA for the inverse

IO.raiseWhen for conditionally raising an error

Source:
IO.scala

Inherited methods

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

Intended for thread blocking operations. blocking will shift the execution of the blocking operation to a separate threadpool to avoid blocking on the main execution context. See the thread-model documentation for more information on why this is necessary. Note that the created effect will be uncancelable; if you need cancelation then you should use [[interruptibleA:*]] or interruptibleMany.

Intended for thread blocking operations. blocking will shift the execution of the blocking operation to a separate threadpool to avoid blocking on the main execution context. See the thread-model documentation for more information on why this is necessary. Note that the created effect will be uncancelable; if you need cancelation then you should use [[interruptibleA:*]] or interruptibleMany.

IO.blocking(scala.io.Source.fromFile("path").mkString)

Attributes

thunk

The side effect which is to be suspended in IO and evaluated on a blocking execution context Implements cats.effect.kernel.Sync.blocking.

Inherited from:
IOCompanionPlatform (hidden)
Source:
IOCompanionPlatform.scala
def fromCompletableFuture[A](fut: IO[CompletableFuture[A]]): IO[A]

Attributes

Inherited from:
IOCompanionPlatform (hidden)
Source:
IOCompanionPlatform.scala
def fromCompletionStage[A](completionStage: IO[CompletionStage[A]]): IO[A]

Attributes

Inherited from:
IOCompanionPlatform (hidden)
Source:
IOCompanionPlatform.scala
def interruptible[A](thunk: => A): IO[A]

Like blocking but will attempt to abort the blocking operation using thread interrupts in the event of cancelation. The interrupt will be attempted only once.

Like blocking but will attempt to abort the blocking operation using thread interrupts in the event of cancelation. The interrupt will be attempted only once.

Note the following tradeoffs:

  • this has slightly more overhead than blocking due to the machinery necessary for the interrupt coordination,
  • thread interrupts are very often poorly considered by Java (and Scala!) library authors, and it is possible for interrupts to result in resource leaks or invalid states. It is important to be certain that this will not be the case before using this mechanism.

Attributes

thunk

The side effect which is to be suspended in IO and evaluated on a blocking execution context Implements [[cats.effect.kernel.Sync.interruptibleA:*]]

Inherited from:
IOCompanionPlatform (hidden)
Source:
IOCompanionPlatform.scala
def interruptibleMany[A](thunk: => A): IO[A]

Like blocking but will attempt to abort the blocking operation using thread interrupts in the event of cancelation. The interrupt will be attempted repeatedly until the blocking operation completes or exits.

Like blocking but will attempt to abort the blocking operation using thread interrupts in the event of cancelation. The interrupt will be attempted repeatedly until the blocking operation completes or exits.

Note the following tradeoffs:

  • this has slightly more overhead than blocking due to the machinery necessary for the interrupt coordination,
  • thread interrupts are very often poorly considered by Java (and Scala!) library authors, and it is possible for interrupts to result in resource leaks or invalid states. It is important to be certain that this will not be the case before using this mechanism.

Attributes

thunk

The side effect which is to be suspended in IO and evaluated on a blocking execution context Implements cats.effect.kernel.Sync!.interruptibleMany

Inherited from:
IOCompanionPlatform (hidden)
Source:
IOCompanionPlatform.scala

Reads a line as a string from the standard input using the platform's default charset, as per java.nio.charset.Charset.defaultCharset().

Reads a line as a string from the standard input using the platform's default charset, as per java.nio.charset.Charset.defaultCharset().

The effect can raise a java.io.EOFException if no input has been consumed before the EOF is observed. This should never happen with the standard input, unless it has been replaced with a finite java.io.InputStream through java.lang.System#setIn or similar.

Attributes

Returns:

an IO effect that describes reading the user's input from the standard input as a string

See also:

cats.effect.std.Console#readLineWithCharset for reading using a custom java.nio.charset.Charset

Inherited from:
IOCompanionPlatform (hidden)
Source:
IOCompanionPlatform.scala
def realTimeInstant: IO[Instant]

Attributes

Inherited from:
IOCompanionPlatform (hidden)
Source:
IOCompanionPlatform.scala
def suspend[A](hint: Type)(thunk: => A): IO[A]

Attributes

Inherited from:
IOCompanionPlatform (hidden)
Source:
IOCompanionPlatform.scala

Deprecated and Inherited methods

def interruptible[A](many: Boolean, thunk: => A): IO[A]

Attributes

Deprecated
true
Inherited from:
IOCompanionPlatform (hidden)
Source:
IOCompanionPlatform.scala

Implicits

Implicits

implicit def alignForIO: Align[IO]

Attributes

Source:
IO.scala
implicit def alignForIOPar: Align[Par]

Attributes

Source:
IO.scala
implicit def asyncForIO: Async[IO]

Attributes

Source:
IO.scala
implicit val consoleForIO: Console[IO]

Attributes

Source:
IO.scala
implicit val envForIO: Env[IO]

Attributes

Source:
IO.scala
implicit def monoidForIO[A : Monoid]: Monoid[IO[A]]

Attributes

Source:
IO.scala
implicit def parallelForIO: Aux[IO, Par]

Attributes

Source:
IO.scala

Attributes

Source:
IO.scala
implicit def showForIO[A : Show]: Show[IO[A]]

Attributes

Source:
IO.scala

Inherited implicits

implicit def semigroupForIO[A : Semigroup]: Semigroup[IO[A]]

Attributes

Inherited from:
IOLowPriorityImplicits (hidden)
Source:
IO.scala
implicit def showForIONoPure[A]: Show[IO[A]]

Attributes

Inherited from:
IOLowPriorityImplicits (hidden)
Source:
IO.scala