cats.effect

package cats.effect

Members list

Type members

Classlikes

sealed abstract case class ExitCode

Represents the exit code of an application.

Represents the exit code of an application.

code is constrained to a range from 0 to 255, inclusive.

Attributes

Companion
object
Source
ExitCode.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object ExitCode

Attributes

Companion
class
Source
ExitCode.scala
Supertypes
class Object
trait Matchable
class Any
Self type
ExitCode.type
sealed abstract class IO[+A]

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

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

IO values are pure, immutable values and thus preserve referential transparency, being usable in functional programming. An IO is a data structure that represents just a description of a side effectful computation.

IO can describe synchronous or asynchronous computations that:

  1. on evaluation yield exactly one result 2. can end in either success or failure and in case of failure flatMap chains get short-circuited (IO implementing the algebra of MonadError) 3. can be canceled, but note this capability relies on the user to provide cancelation logic

Effects described via 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:

val ioa = IO.println("hey!")

val program = for {
 _ <- ioa
 _ <- ioa
} yield ()

program.unsafeRunSync()

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 in its flatMap evaluation. This means that you can safely call flatMap in a recursive function of arbitrary depth, without fear of blowing the stack.

def fib(n: Int, a: Long = 0, b: Long = 1): IO[Long] =
 IO.pure(a + b) flatMap { b2 =>
   if (n > 0)
     fib(n - 1, b, b2)
   else
     IO.pure(a)
 }

Attributes

See also

IOApp for the preferred way of executing whole programs wrapped in IO

Companion
object
Source
IO.scala
Supertypes
trait Serializable
class Object
trait Matchable
class Any
object IO

Attributes

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

The primary entry point to a Cats Effect application. Extend this trait rather than defining your own main method. This avoids the need to run IO.unsafeRunSync (or similar) on your own.

The primary entry point to a Cats Effect application. Extend this trait rather than defining your own main method. This avoids the need to run IO.unsafeRunSync (or similar) on your own.

IOApp takes care of the messy details of properly setting up (and tearing down) the unsafe.IORuntime needed to run the IO which represents your application. All of the associated thread pools (if relevant) will be configured with the assumption that your application is fully contained within the IO produced by the run method. Note that the exact details of how the runtime will be configured are very platform-specific. Part of the point of IOApp is to insulate users from the details of the underlying runtime (whether JVM or JavaScript).

 object MyApplication extends IOApp {
   def run(args: List[String]) =
     for {
       _ <- IO.print("Enter your name: ")
       name <- IO.readln
       _ <- IO.println("Hello, " + name)
     } yield ExitCode.Success
 }

In the above example, MyApplication will be a runnable class with a main method, visible to Sbt, IntelliJ, or plain-old java. When run externally, it will print, read, and print in the obvious way, producing a final process exit code of 0. Any exceptions thrown within the IO will be printed to standard error and the exit code will be set to 1. In the event that the main Fiber (represented by the IO returned by run) is canceled, the runtime will produce an exit code of 1.

Note that exit codes are an implementation-specific feature of the underlying runtime, as are process arguments. Naturally, all JVMs support these functions, as does Node.js and Scala Native, but some JavaScript execution environments will be unable to replicate these features (or they simply may not make sense). In such cases, exit codes may be ignored and/or argument lists may be empty.

Note that in the case of the above example, we would actually be better off using IOApp.Simple rather than IOApp directly, since we are neither using args nor are we explicitly producing a custom ExitCode:

 object MyApplication extends IOApp.Simple {
   val run =
     for {
       _ <- IO.print("Enter your name: ")
       name <- IO.readln
       _ <- IO.println(s"Hello, " + name)
     } yield ()
 }

It is valid to define val run rather than def run because IO's evaluation is lazy: it will only run when the main method is invoked by the runtime.

In the event that the process receives an interrupt signal (SIGINT) due to Ctrl-C (or any other mechanism), it will immediately cancel the main fiber. Assuming this fiber is not within an uncancelable region, this will result in interrupting any current activities and immediately invoking any finalizers (see: IO.onCancel and IO.bracket). The process will not shut down until the finalizers have completed. For example:

 object InterruptExample extends IOApp.Simple {
   val run =
     IO.bracket(startServer)(
       _ => IO.never)(
       server => IO.println("shutting down") *> server.close)
 }

If we assume the startServer function has type IO[Server] (or similar), this kind of pattern is very common. When this process receives a SIGINT, it will immediately print "shutting down" and run the server.close effect.

One consequence of this design is it is possible to build applications which will ignore process interrupts. For example, if server.close runs forever, the process will ignore interrupts and will need to be cleaned up using SIGKILL (i.e. kill -9). This same phenomenon can be demonstrated by using IO.uncancelable to suppress all interruption within the application itself:

 object Zombie extends IOApp.Simple {
   val run = IO.never.uncancelable
 }

The above process will run forever and ignore all interrupts. The only way it will shut down is if it receives SIGKILL.

It is possible (though not necessary) to override various platform-specific runtime configuration options, such as computeWorkerThreadCount (which only exists on the JVM). Please note that the default configurations have been extensively benchmarked and are optimal (or close to it) in most conventional scenarios.

However, with that said, there really is no substitute to benchmarking your own application. Every application and scenario is unique, and you will always get the absolute best results by performing your own tuning rather than trusting someone else's defaults. IOApp's defaults are very ''good'', but they are not perfect in all cases. One common example of this is applications which maintain network or file I/O worker threads which are under heavy load in steady-state operations. In such a performance profile, it is usually better to reduce the number of compute worker threads to "make room" for the I/O workers, such that they all sum to the number of physical threads exposed by the kernel.

Attributes

See also
Companion
object
Source
IOApp.scala
Supertypes
class Object
trait Matchable
class Any
Known subtypes
trait Simple
object IOApp

Attributes

Companion
trait
Source
IOApp.scala
Supertypes
class Object
trait Matchable
class Any
Self type
IOApp.type
sealed trait IOLocal[A]

IOLocal provides a handy way of manipulating a context on different scopes.

IOLocal provides a handy way of manipulating a context on different scopes.

In some scenarios, IOLocal can be considered as an alternative to cats.data.Kleisli.

IOLocal should not be treated as Ref, since the former abides different laws.

Once a fiber is forked, for example by Spawn[F].start, the forked fiber manipulates the copy of the parent's context. For example, two forked fibers will never see each other's modifications to the same IOLocal, each fiber will only see its own modifications.

===Operations on IOLocal are visible to the fiber===

┌────────────┐               ┌────────────┐               ┌────────────┐
│  Fiber A   │ update(_ + 1) │  Fiber A   │ update(_ + 1) │  Fiber A   │
│ (local 42) │──────────────►│ (local 43) │──────────────►│ (local 44) │
└────────────┘               └────────────┘               └────────────┘
def inc(name: String, local: IOLocal[Int]): IO[Unit] =
  local.update(_ + 1) >> local.get.flatMap(current => IO.println(s"fiber $$name: $$current"))

for {
  local   <- IOLocal(42)
  _       <- inc(1, local)
  _       <- inc(2, local)
  current <- local.get
  _       <- IO.println(s"fiber A: $$current")
} yield ()

// output:
// update 1: 43
// update 2: 44
// fiber A: 44

===A forked fiber operates on a copy of the parent IOLocal===

A '''forked''' fiber (i.e. via Spawn[F].start) operates on a '''copy''' of the parent IOLocal. Hence, the children operations are not reflected on the parent context.

                     ┌────────────┐               ┌────────────┐
                fork │  Fiber B   │ update(_ - 1) │  Fiber B   │
              ┌─────►│ (local 42) │──────────────►│ (local 41) │
              │      └────────────┘               └────────────┘
┌────────────┐─┘                                   ┌────────────┐
│  Fiber A   │                                     │  Fiber A   │
│ (local 42) │────────────────────────────────────►│ (local 42) │
└────────────┘─┐                                   └────────────┘
              │      ┌────────────┐               ┌────────────┐
              │ fork │  Fiber C   │ update(_ + 1) │  Fiber C   │
              └─────►│ (local 42) │──────────────►│ (local 43) │
                     └────────────┘               └────────────┘
def update(name: String, local: IOLocal[Int], f: Int => Int): IO[Unit] =
  local.update(f) >> local.get.flatMap(current => IO.println(s"$$name: $$current"))

for {
  local   <- IOLocal(42)
  fiber1  <- update("fiber B", local, _ - 1).start
  fiber2  <- update("fiber C", local, _ + 1).start
  _       <- fiber1.joinWithNever
  _       <- fiber2.joinWithNever
  current <- local.get
  _       <- IO.println(s"fiber A: $$current")
} yield ()

// output:
// fiber B: 41
// fiber C: 43
// fiber A: 42

===Parent operations on IOLocal are invisible to children===

                     ┌────────────┐               ┌────────────┐
                fork │  Fiber B   │ update(_ + 1) │  Fiber B   │
              ┌─────►│ (local 42) │──────────────►│ (local 43) │
              │      └────────────┘               └────────────┘
┌────────────┐─┘                                   ┌────────────┐
│  Fiber A   │        update(_ - 1)                │  Fiber A   │
│ (local 42) │────────────────────────────────────►│ (local 41) │
└────────────┘─┐                                   └────────────┘
              │      ┌────────────┐               ┌────────────┐
              │ fork │  Fiber C   │ update(_ + 2) │  Fiber C   │
              └─────►│ (local 42) │──────────────►│ (local 44) │
                     └────────────┘               └────────────┘
def update(name: String, local: IOLocal[Int], f: Int => Int): IO[Unit] =
  IO.sleep(1.second) >> local.update(f) >> local.get.flatMap(current => IO.println(s"$$name: $$current"))

for {
  local  <- IOLocal(42)
  fiber1 <- update("fiber B", local, _ + 1).start
  fiber2 <- update("fiber C", local, _ + 2).start
  _      <- fiber1.joinWithNever
  _      <- fiber2.joinWithNever
  _      <- update("fiber A", local, _ - 1)
} yield ()

// output:
// fiber B: 43
// fiber C: 44
// fiber A: 41

Type parameters

A

the type of the local value

Attributes

Companion
object
Source
IOLocal.scala
Supertypes
class Object
trait Matchable
class Any
Self type
IOLocal[A]
object IOLocal

Attributes

Companion
trait
Source
IOLocal.scala
Supertypes
class Object
trait Matchable
class Any
Self type
IOLocal.type
trait LiftIO[F[_]]

Attributes

Companion
object
Source
LiftIO.scala
Supertypes
class Object
trait Matchable
class Any
object LiftIO

Attributes

Companion
trait
Source
LiftIO.scala
Supertypes
class Object
trait Matchable
class Any
Self type
LiftIO.type
trait ResourceApp

A convenience trait for defining applications which are entirely within Resource. This is implemented as a relatively straightforward wrapper around IOApp and thus inherits most of its functionality and semantics.

A convenience trait for defining applications which are entirely within Resource. This is implemented as a relatively straightforward wrapper around IOApp and thus inherits most of its functionality and semantics.

This trait should generally be used for any application which would otherwise trivially end with cats.effect.kernel.Resource!.use (or one of its variants). For example:

 object HttpExample extends IOApp {
   def run(args: List[String]) = {
     val program = for {
       config <- Resource.eval(loadConfig(args.head))
       postgres <- Postgres[IO](config.jdbcUri)
       endpoints <- ExampleEndpoints[IO](config, postgres)
       _ <- HttpServer[IO](config.host, config.port, endpoints)
     } yield ()

     program.useForever.as(ExitCode.Success)
   }
 }

This example assumes some underlying libraries like Skunk and Http4s, but otherwise it represents a relatively typical example of what the main class for a realistic Cats Effect application might look like. Notably, the whole thing is enclosed in Resource, which is used at the very end. This kind of pattern is so common that ResourceApp defines a special trait which represents it. We can rewrite the above example:

 object HttpExample extends ResourceApp.Forever {
   def run(args: List[String]) =
     for {
       config <- Resource.eval(loadConfig(args.head))
       db <- Postgres[IO](config.jdbcUri)
       endpoints <- ExampleEndpoints[IO](config, db)
       _ <- HttpServer[IO](config.host, config.port, endpoints)
     } yield ()
 }

These two programs are equivalent.

Attributes

See also
Companion
object
Source
ResourceApp.scala
Supertypes
class Object
trait Matchable
class Any
Known subtypes
trait Simple
Self type
object ResourceApp

Attributes

Companion
trait
Source
ResourceApp.scala
Supertypes
class Object
trait Matchable
class Any
Self type
trait Selector

Attributes

Source
Selector.scala
Supertypes
class Object
trait Matchable
class Any
Known subtypes
class SelectorImpl
sealed abstract class SyncIO[+A] extends Serializable

A pure abstraction representing the intention to perform a side effect, where the result of that side effect is obtained synchronously.

A pure abstraction representing the intention to perform a side effect, where the result of that side effect is obtained synchronously.

SyncIO is similar to IO, but does not support asynchronous computations. Consequently, a SyncIO can be run synchronously on any platform to obtain a result via unsafeRunSync. This is unlike IO#unsafeRunSync, which cannot be safely called in general -- doing so on the JVM blocks the calling thread while the async part of the computation is run and doing so on Scala.js is not supported.

Attributes

Companion
object
Source
SyncIO.scala
Supertypes
trait Serializable
class Object
trait Matchable
class Any
object SyncIO

Attributes

Companion
class
Source
SyncIO.scala
Supertypes
trait Sum
trait Mirror
class Object
trait Matchable
class Any
Self type
SyncIO.type
final class Trace

Attributes

Source
Trace.scala
Supertypes
class Object
trait Matchable
class Any
object implicits extends AllSyntax, AllInstances

Attributes

Source
implicits.scala
Supertypes
trait AllInstances
trait AllSyntax
trait AllSyntax
trait AllSyntax
trait ClockSyntax
trait AsyncSyntax
class Object
trait Matchable
class Any
Show all
Self type
implicits.type

Types

type Async[F[_]] = Async[F]

Attributes

Source
package.scala
type Clock[F[_]] = Clock[F]

Attributes

Source
package.scala
type Concurrent[F[_]] = Concurrent[F]

Attributes

Source
package.scala
type Cont[F[_], K, R] = Cont[F, K, R]

Attributes

Source
package.scala
type Deferred[F[_], A] = Deferred[F, A]

Attributes

Source
package.scala
type Fiber[F[_], E, A] = Fiber[F, E, A]

Attributes

Source
package.scala
type FiberIO[A] = Fiber[IO, Throwable, A]

Attributes

Source
package.scala
type GenConcurrent[F[_], E] = GenConcurrent[F, E]

Attributes

Source
package.scala
type GenSpawn[F[_], E] = GenSpawn[F, E]

Attributes

Source
package.scala
type GenTemporal[F[_], E] = GenTemporal[F, E]

Attributes

Source
package.scala
type MonadCancel[F[_], E] = MonadCancel[F, E]

Attributes

Source
package.scala

Attributes

Source
package.scala
type Outcome[F[_], E, A] = Outcome[F, E, A]

Attributes

Source
package.scala
type OutcomeIO[A] = Outcome[IO, Throwable, A]

Attributes

Source
package.scala
type ParallelF[F[_], A] = T[F, A]

Attributes

Source
package.scala
type Poll[F[_]] = Poll[F]

Attributes

Source
package.scala
type Ref[F[_], A] = Ref[F, A]

Attributes

Source
package.scala
type Resource[F[_], +A] = Resource[F, A]

Attributes

Source
package.scala
type ResourceIO[A] = Resource[IO, A]

Attributes

Source
package.scala
type Spawn[F[_]] = Spawn[F]

Attributes

Source
package.scala
type Sync[F[_]] = Sync[F]

Attributes

Source
package.scala
type Temporal[F[_]] = Temporal[F]

Attributes

Source
package.scala
type Unique[F[_]] = Unique[F]

Attributes

Source
package.scala

Value members

Concrete fields

val Async: Async.type

Attributes

Source
package.scala
val Clock: Clock.type

Attributes

Source
package.scala

Attributes

Source
package.scala
val Deferred: Deferred.type

Attributes

Source
package.scala

Attributes

Source
package.scala
val GenSpawn: GenSpawn.type

Attributes

Source
package.scala

Attributes

Source
package.scala

Attributes

Source
package.scala

Attributes

Source
package.scala
val Outcome: Outcome.type

Attributes

Source
package.scala
val ParallelF: ParallelF.type

Attributes

Source
package.scala
val Ref: Ref.type

Attributes

Source
package.scala
val Resource: Resource.type

Attributes

Source
package.scala
val Spawn: GenSpawn.type

Attributes

Source
package.scala
val Sync: Sync.type

Attributes

Source
package.scala
val Temporal: GenTemporal.type

Attributes

Source
package.scala
val Unique: Unique.type

Attributes

Source
package.scala