Packages

sealed abstract class Coeval[+A] extends () ⇒ A with Serializable

Coeval represents lazy computations that can execute synchronously.

Word definition and origin:

  • Having the same age or date of origin; a contemporary; synchronous.
  • From the Latin "coævus": com- ‎("equal") in combination with aevum ‎(aevum, "age").
  • The constructor of Coeval is the dual of an expression that evaluates to an A.

There are three evaluation strategies:

  • now or raiseError: for describing strict values, evaluated immediately
  • evalOnce: expressions evaluated a single time
  • eval: expressions evaluated every time the value is needed

The Once and Always are both lazy strategies while Now and Error are eager. Once and Always are distinguished from each other only by memoization: once evaluated Once will save the value to be returned immediately if it is needed again. Always will run its computation every time.

Both Now and Error are represented by the Eager trait, a sub-type of Coeval that can be used as a replacement for Scala's own Try type.

Coeval supports stack-safe lazy computation via the .map and .flatMap methods, which use an internal trampoline to avoid stack overflows. Computations done within .map and .flatMap are always lazy, even when applied to a Coeval.Eager instance (e.g. Coeval.Now, Coeval.Error).

Evaluation Strategies

The "now" and "raiseError" builders are building Coeval instances out of strict values:

val fa = Coeval.now(1)
fa.value //=> 1

val fe = Coeval.raiseError(new DummyException("dummy"))
fe.value //=> throws DummyException

The "always" strategy is equivalent with a plain function:

// For didactic purposes, don't use shared vars at home :-)
var i = 0
val fa = Coeval.eval { i += 1; i }

fa.value //=> 1
fa.value //=> 2
fa.value //=> 3

The "once" strategy is equivalent with Scala's lazy val (along with thread-safe idempotency guarantees):

var i = 0
val fa = Coeval.evalOnce { i += 1; i }

fa.value //=> 1
fa.value //=> 1
fa.value //=> 1

Versus Task

The other option of suspending side-effects is Task. As a quick comparison:

  • Coeval's execution is always immediate / synchronous, whereas Task can describe asynchronous computations
  • Coeval is not cancelable, obviously, since execution is immediate and there's nothing to cancel

Versus cats.Eval

The Coeval data type is very similar with cats.Eval. As a quick comparison:

  • cats.Eval is only for controlling laziness, but it doesn't handle side effects, hence cats.Eval is a Comonad
  • Monix's Coeval can handle side effects as well and thus it implements MonadError[Coeval, Throwable] and cats.effect.Sync, providing error-handling utilities

If you just want to delay the evaluation of a pure expression use cats.Eval, but if you need to suspend side effects or you need error handling capabilities, then use Coeval.

Self Type
Coeval[A]
Linear Supertypes
Serializable, Serializable, () ⇒ A, AnyRef, Any
Known Subclasses
Ordering
  1. Alphabetic
  2. By Inheritance
Inherited
  1. Coeval
  2. Serializable
  3. Serializable
  4. Function0
  5. AnyRef
  6. Any
  1. Hide All
  2. Show All
Visibility
  1. Public
  2. All

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

    Evaluates the underlying computation and returns the result.

    Evaluates the underlying computation and returns the result.

    NOTE: this can throw exceptions.

    // For didactic purposes, don't do shared vars at home :-)
    var i = 0
    val fa = Coeval { i += 1; i }
    
    fa() //=> 1
    fa() //=> 2
    fa() //=> 3
    Definition Classes
    Coeval → Function0
  5. final def asInstanceOf[T0]: T0
    Definition Classes
    Any
  6. final def attempt: Coeval[Either[Throwable, A]]

    Creates a new Coeval that will expose any triggered error from the source.

    Creates a new Coeval that will expose any triggered error from the source.

    val fa: Coeval[Int] =
      Coeval.raiseError[Int](new DummyException("dummy"))
    
    val fe: Coeval[Either[Throwable, Int]] =
      fa.attempt
    
    fe.flatMap {
      case Left(_) => Int.MaxValue
      case Right(v) => v
    }

    By exposing errors by lifting the Coeval's result into an Either value, we can handle those errors in flatMap transformations.

    Also see materialize for working with Scala's Try or transformWith for an alternative.

  7. def clone(): AnyRef
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @native() @throws( ... )
  8. final def dematerialize[B](implicit ev: <:<[A, Try[B]]): Coeval[B]

    Dematerializes the source's result from a Try.

    Dematerializes the source's result from a Try.

    This equivalence always holds:

    scala fa.materialize.dematerialize <-> fa

  9. final def doOnFinish(f: (Option[Throwable]) ⇒ Coeval[Unit]): Coeval[A]

    Returns a new Coeval in which f is scheduled to be run on completion.

    Returns a new Coeval in which f is scheduled to be run on completion. This would typically be used to release any resources acquired by this Coeval.

  10. final def eq(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  11. def equals(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  12. final def failed: Coeval[Throwable]

    Returns a failed projection of this coeval.

    Returns a failed projection of this coeval.

    The failed projection is a Coeval holding a value of type Throwable, emitting the error yielded by the source, in case the source fails, otherwise if the source succeeds the result will fail with a NoSuchElementException.

  13. def finalize(): Unit
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( classOf[java.lang.Throwable] )
  14. final def flatMap[B](f: (A) ⇒ Coeval[B]): Coeval[B]

    Creates a new Coeval by applying a function to the successful result of the source, and returns a new instance equivalent to the result of the function.

    Creates a new Coeval by applying a function to the successful result of the source, and returns a new instance equivalent to the result of the function.

    The application of flatMap is always lazy and because of the implementation it is memory safe and thus it can be used in recursive loops.

    Sample:

    def randomEven: Coeval[Int] =
      Coeval(Random.nextInt()).flatMap { x =>
        if (x < 0 || x % 2 == 1)
          randomEven // retry
        else
          Coeval.now(x)
      }
  15. final def flatten[B](implicit ev: <:<[A, Coeval[B]]): Coeval[B]

    Given a source Coeval that emits another Coeval, this function flattens the result, returning a Coeval equivalent to the emitted Coeval by the source.

    Given a source Coeval that emits another Coeval, this function flattens the result, returning a Coeval equivalent to the emitted Coeval by the source.

    This equivalence with flatMap always holds:

    scala fa.flatten <-> fa.flatMap(x => x)

  16. final def foreach(f: (A) ⇒ Unit): Unit

    Triggers the evaluation of the source, executing the given function for the generated element.

    Triggers the evaluation of the source, executing the given function for the generated element.

    The application of this function has strict behavior, as the coeval is immediately executed.

  17. final def foreachL(f: (A) ⇒ Unit): Coeval[Unit]

    Returns a new task that upon evaluation will execute the given function for the generated element, transforming the source into a Coeval[Unit].

    Returns a new task that upon evaluation will execute the given function for the generated element, transforming the source into a Coeval[Unit].

    Similar in spirit with normal foreach, but lazy, as obviously nothing gets executed at this point.

  18. final def getClass(): Class[_]
    Definition Classes
    AnyRef → Any
    Annotations
    @native()
  19. def hashCode(): Int
    Definition Classes
    AnyRef → Any
    Annotations
    @native()
  20. final def isInstanceOf[T0]: Boolean
    Definition Classes
    Any
  21. final def map[B](f: (A) ⇒ B): Coeval[B]

    Returns a new Coeval that applies the mapping function to the element emitted by the source.

    Returns a new Coeval that applies the mapping function to the element emitted by the source.

    Can be used for specifying a (lazy) transformation to the result of the source.

    This equivalence with flatMap always holds:

    scala fa.map(f) <-> fa.flatMap(x => Coeval.pure(f(x)))

  22. final def materialize: Coeval[Try[A]]

    Creates a new Coeval that will expose any triggered error from the source.

    Creates a new Coeval that will expose any triggered error from the source.

    Also see attempt for working with Scala's Either or transformWith for an alternative.

  23. final def memoize: Coeval[A]

    Memoizes (caches) the result of the source and reuses it on subsequent invocations of value.

    Memoizes (caches) the result of the source and reuses it on subsequent invocations of value.

    The resulting coeval will be idempotent, meaning that evaluating the resulting coeval multiple times will have the same effect as evaluating it once.

    See also

    memoizeOnSuccess for a version that only caches successful results

  24. final def memoizeOnSuccess: Coeval[A]

    Memoizes (cache) the successful result of the source and reuses it on subsequent invocations of value.

    Memoizes (cache) the successful result of the source and reuses it on subsequent invocations of value. Thrown exceptions are not cached.

    The resulting coeval will be idempotent, but only if the result is successful.

    See also

    memoize for a version that caches both successful results and failures

  25. final def ne(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  26. final def notify(): Unit
    Definition Classes
    AnyRef
    Annotations
    @native()
  27. final def notifyAll(): Unit
    Definition Classes
    AnyRef
    Annotations
    @native()
  28. final def onErrorFallbackTo[B >: A](that: Coeval[B]): Coeval[B]

    Creates a new coeval that in case of error will fallback to the given backup coeval.

  29. final def onErrorHandle[U >: A](f: (Throwable) ⇒ U): Coeval[U]

    Creates a new coeval that will handle any matching throwable that this coeval might emit.

    Creates a new coeval that will handle any matching throwable that this coeval might emit.

    See onErrorRecover for the version that takes a partial function.

  30. final def onErrorHandleWith[B >: A](f: (Throwable) ⇒ Coeval[B]): Coeval[B]

    Creates a new coeval that will handle any matching throwable that this coeval might emit by executing another coeval.

    Creates a new coeval that will handle any matching throwable that this coeval might emit by executing another coeval.

    See onErrorRecoverWith for the version that takes a partial function.

  31. final def onErrorRecover[U >: A](pf: PartialFunction[Throwable, U]): Coeval[U]

    Creates a new coeval that on error will try to map the error to another value using the provided partial function.

    Creates a new coeval that on error will try to map the error to another value using the provided partial function.

    See onErrorHandle for the version that takes a total function.

  32. final def onErrorRecoverWith[B >: A](pf: PartialFunction[Throwable, Coeval[B]]): Coeval[B]

    Creates a new coeval that will try recovering from an error by matching it with another coeval using the given partial function.

    Creates a new coeval that will try recovering from an error by matching it with another coeval using the given partial function.

    See onErrorHandleWith for the version that takes a total function.

  33. final def onErrorRestart(maxRetries: Long): Coeval[A]

    Creates a new coeval that in case of error will retry executing the source again and again, until it succeeds.

    Creates a new coeval that in case of error will retry executing the source again and again, until it succeeds.

    In case of continuous failure the total number of executions will be maxRetries + 1.

  34. final def onErrorRestartIf(p: (Throwable) ⇒ Boolean): Coeval[A]

    Creates a new coeval that in case of error will retry executing the source again and again, until it succeeds.

    Creates a new coeval that in case of error will retry executing the source again and again, until it succeeds.

    In case of continuous failure the total number of executions will be maxRetries + 1.

  35. final def restartUntil(p: (A) ⇒ Boolean): Coeval[A]

    Given a predicate function, keep retrying the coeval until the function returns true.

  36. def run: Eager[A]

    Evaluates the underlying computation, reducing this Coeval to a Coeval.Eager value, with successful results being signaled with Coeval.Now and failures with Coeval.Error.

    Evaluates the underlying computation, reducing this Coeval to a Coeval.Eager value, with successful results being signaled with Coeval.Now and failures with Coeval.Error.

    val fa = Coeval.eval(10 * 2)
    
    fa.run match {
      case Coeval.Now(value) =>
        println("Success: " + value)
      case Coeval.Error(e) =>
        e.printStackTrace()
    }

    See runAttempt for working with Either values and runTry for working with Try values. See apply for a partial function (that may throw exceptions in case of failure).

  37. def runAttempt: Either[Throwable, A]

    Evaluates the underlying computation and returns the result or any triggered errors as a Scala Either, where Right(_) is for successful values and Left(_) is for thrown errors.

    Evaluates the underlying computation and returns the result or any triggered errors as a Scala Either, where Right(_) is for successful values and Left(_) is for thrown errors.

    val fa = Coeval(10 * 2)
    
    fa.runAttempt match {
      case Right(value) =>
        println("Success: " + value)
      case Left(e) =>
        e.printStackTrace()
    }

    See run for working with Coeval.Eager values and runTry for working with Try values. See apply for a partial function (that may throw exceptions in case of failure).

  38. def runTry: Try[A]

    Evaluates the underlying computation and returns the result or any triggered errors as a scala.util.Try.

    Evaluates the underlying computation and returns the result or any triggered errors as a scala.util.Try.

    val fa = Coeval(10 * 2)
    
    fa.runTry match {
      case Success(value) =>
        println("Success: " + value)
      case Failure(e) =>
        e.printStackTrace()
    }

    See run for working with Coeval.Eager values and runAttempt for working with Either values. See apply for a partial function (that may throw exceptions in case of failure).

  39. final def synchronized[T0](arg0: ⇒ T0): T0
    Definition Classes
    AnyRef
  40. final def task: Task[A]

    Converts the source Coeval into a Task.

  41. final def toEval: Eval[A]

    Converts the source Coeval into a cats.Eval.

  42. final def toIO: IO[A]

    Converts the source Coeval into a cats.effect.IO.

  43. def toString(): String
    Definition Classes
    Coeval → Function0 → AnyRef → Any
  44. final def transform[R](fa: (A) ⇒ R, fe: (Throwable) ⇒ R): Coeval[R]

    Creates a new Coeval by applying the 'fa' function to the successful result of this future, or the 'fe' function to the potential errors that might happen.

    Creates a new Coeval by applying the 'fa' function to the successful result of this future, or the 'fe' function to the potential errors that might happen.

    This function is similar with map, except that it can also transform errors and not just successful results.

    For example attempt can be expressed in terms of transform:

    source.transform(v => Right(v), e => Left(e))

    And materialize too:

    source.transform(v => Success(v), e => Failure(e))
    fa

    function that transforms a successful result of the receiver

    fe

    function that transforms an error of the receiver

  45. final def transformWith[R](fa: (A) ⇒ Coeval[R], fe: (Throwable) ⇒ Coeval[R]): Coeval[R]

    Creates a new Coeval by applying the 'fa' function to the successful result of this future, or the 'fe' function to the potential errors that might happen.

    Creates a new Coeval by applying the 'fa' function to the successful result of this future, or the 'fe' function to the potential errors that might happen.

    This function is similar with flatMap, except that it can also transform errors and not just successful results.

    For example attempt can be expressed in terms of transformWith:

    source.transformWith(
      v => Coeval.now(Right(v)),
      e => Coeval.now(Left(e))
    )
    fa

    function that transforms a successful result of the receiver

    fe

    function that transforms an error of the receiver

  46. def value: A

    Evaluates the underlying computation and returns the result.

    Evaluates the underlying computation and returns the result.

    NOTE: this can throw exceptions.

    Alias for apply.

  47. final def wait(): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  48. final def wait(arg0: Long, arg1: Int): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  49. final def wait(arg0: Long): Unit
    Definition Classes
    AnyRef
    Annotations
    @native() @throws( ... )
  50. final def zip[B](that: Coeval[B]): Coeval[(A, B)]

    Zips the values of this and that coeval, and creates a new coeval that will emit the tuple of their results.

  51. final def zipMap[B, C](that: Coeval[B])(f: (A, B) ⇒ C): Coeval[C]

    Zips the values of this and that and applies the given mapping function on their results.

Inherited from Serializable

Inherited from Serializable

Inherited from () ⇒ A

Inherited from AnyRef

Inherited from Any

Ungrouped