arrow-core-data / arrow.core / Eval

Eval

@higherkind sealed class Eval<out A> : EvalOf<A>

Eval is a monad which controls evaluation of a value or a computation that produces a value.

Three basic evaluation strategies:

  • Now: evaluated immediately
  • Later: evaluated once when value is needed
  • Always: evaluated every time value is needed

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

methods, which use an internal trampoline to avoid stack overflows. Computation done within .map and .flatMap is always done lazily, even when applied to a Now instance.

It is not generally good style to pattern-match on Eval instances. Rather, use .map and .flatMap to chain computation, and use .value to get the result when needed. It is also not good style to create Eval instances whose computation involves calling .value on another Eval instance – this can defeat the trampolining and lead to stack overflows.

Example of stack safety:


import arrow.core.Eval

//sampleStart
fun even(n: Int): Eval<Boolean> =
  Eval.always { n == 0 }.flatMap {
    if(it == true) Eval.now(true)
    else odd(n - 1)
  }

fun odd(n: Int): Eval<Boolean> =
  Eval.always { n == 0 }.flatMap {
    if(it == true) Eval.now(false)
    else even(n - 1)
  }

// if not wrapped in eval this type of computation would blow the stack and result in a StackOverflowError
fun main() {
  println(odd(100000).value())
}
//sampleEnd

Types

Always data class Always<out A> : Eval<A>
Construct a lazy Eval instance.
Defer data class Defer<out A> : Eval<A>
Defer is a type of Eval that is used to defer computations which produce Eval.
Later data class Later<out A> : Eval<A>
Construct a lazy Eval instance.
Now data class Now<out A> : Eval<A>
Construct an eager Eval instance. In some sense it is equivalent to using a val.

Functions

ap fun <B> ap(ff: EvalOf<(A) -> B>): Eval<B>
coflatMap fun <B> coflatMap(f: (EvalOf<A>) -> B): Eval<B>
extract fun extract(): A
flatMap fun <B> flatMap(f: (A) -> EvalOf<B>): Eval<B>
map fun <B> map(f: (A) -> B): Eval<B>
memoize abstract fun memoize(): Eval<A>
value abstract fun value(): A

Companion Object Properties

False val False: Eval<Boolean>
One val One: Eval<Int>
True val True: Eval<Boolean>
Unit val Unit: Eval<Unit>
Zero val Zero: Eval<Int>

Companion Object Functions

always fun <A> always(f: () -> A): Eval.Always<A>
Creates an Eval instance from a function deferring it’s evaluation until .value() is invoked recomputing each time .value() is invoked.
defer fun <A> defer(f: () -> Eval<A>): Eval<A>
just fun <A> just(a: A): Eval<A>
later fun <A> later(f: () -> A): Eval.Later<A>
Creates an Eval instance from a function deferring it’s evaluation until .value() is invoked memoizing the computed value.
now fun <A> now(a: A): Eval.Now<A>
Creates an Eval instance from an already constructed value but still defers evaluation when chaining expressions with map and flatMap
raise fun raise(t: Throwable): Eval<Nothing>
tailRecM fun <A, B> tailRecM(a: A, f: (A) -> EvalOf<Either<A, B>>): Eval<B>

Extension Functions

const fun <A> A.const(): Const<A, Nothing>
fix fun <A> EvalOf<A>.fix(): Eval<A>
invalid fun <E> E.invalid(): Validated<E, Nothing>
invalidNel fun <E> E.invalidNel(): ValidatedNel<E, Nothing>
left fun <A> A.left(): Either<A, Nothing>
leftIor fun <A> A.leftIor(): Ior<A, Nothing>
nel fun <A> A.nel(): NonEmptyList<A>
right fun <A> A.right(): Either<Nothing, A>
rightIfNotNull fun <A, B> B?.rightIfNotNull(default: () -> A): Either<A, B>
Returns Either.Right if the value of type B is not null, otherwise the specified A value wrapped into an Either.Left.
rightIfNull fun <A> Any?.rightIfNull(default: () -> A): Either<A, Nothing?>
Returns Either.Right if the value of type Any? is null, otherwise the specified A value wrapped into an Either.Left.
rightIor fun <A> A.rightIor(): Ior<Nothing, A>
some fun <A> A.some(): Option<A>
success fun <A> A.~~success~~(): Try<A>
toOption fun <T> T?.toOption(): Option<T>
toT infix fun <A, B> A.toT(b: B): Tuple2<A, B>
valid fun <A> A.valid(): Validated<Nothing, A>
validNel fun <A> A.validNel(): ValidatedNel<Nothing, A>
value fun <A> EvalOf<A>.value(): A

Inheritors

Always data class Always<out A> : Eval<A>
Construct a lazy Eval instance.
Defer data class Defer<out A> : Eval<A>
Defer is a type of Eval that is used to defer computations which produce Eval.
Later data class Later<out A> : Eval<A>
Construct a lazy Eval instance.
Now data class Now<out A> : Eval<A>
Construct an eager Eval instance. In some sense it is equivalent to using a val.