Arrow 2.2.0
Arrow 2.2.0 is out, with improved and new functionality. This release builds on top of several new features in Kotlin 2.2, in its self-imposed role of perfect companion for your Kotlin journey.
Raise with context parameters.
The new package arrow.core.raise.context provides the same API as arrow.core.raise,
but using context parameters instead of extension functions.
This package is intended to be a full 1-1 replacement the extension-based API.
Unfortunately, currently mixing Raise functions using extension-style and
context-style doesn't lead to the better experience. Our advice is to fully migrate
to the context-style API if possible, or stay completely within the extension style.
// extension-style
fun Raise<PersonValidationError>.buildPerson(name: String, age: Int): Person { ... }
// context-style, "fake" constructor
context(Raise<PersonValidationError>)
fun Person(name: String, age: Int): Person { ... }
In order to define functions with context parameters, you need to enable the corresponding language feature, as described in the Kotlin documentation.
New Racing DSL for concurrency.
Arrow Fx provides high-level concurrency combinators
to succinctly describe how tasks should be interleaved in a computation.
Albeit useful, those combinators require nesting and writing your code in a
particular way. In Arrow 2.2.0 we introduce a new
Racing DSL.
Combined with the already existing
AwaitAll DSL,
you can write your coroutines code with little to no changes, while using as
much concurrency as possible during execution.
validate for error values.
We have introduced a small utility function to bridge the world of validation functions
working on Raise, and chained style using Either or Option. This function is
called validate, and it should be commonly used in conjunction with ensure and similar functions.
fun failOnMoreConditionsWithBindMap(): Either<String, Int> =
    randomNumber()
        .validate { ensure(it != 10) { "Number 10 also not allowed" } }
        .map { it + 100 }
This new function provides no functionality you could not get before.
For example, here is the code equivalent to the one above, but using the Either DSL.
fun failOnMoreConditionsWithBindMap(): Either<String, Int> = either {
    val random = randomNumber().bind()
    ensure(random != 10) { "Number 10 also not allowed" }
    random + 100
}
We acknowledge that the chain-of-calls style is a common one, and we want the Arrow API to appeal to users using their preferred style.
"At most once" for Eval.
Arrow provides the Eval type for fine-grained control over evaluation.
This is similar to lazy in the standard library, but you can choose
between eager, lazy, and repeated (computed every time) evaluation strategies.
However, there was no (easy) way to ensure that a computation was evaluated
at most once.
The new Eval.atMostOnce function (alongside SuspendEval.atMostOnce)
provides this new behavior. You should be aware, though, that this means
that getting the value of an Eval built this way may block (or suspend)
if more than one thread does so concurrently.
Changes to toString for non-empty collections.
After a long discussion in Slack
it became clear that the behavior of toString for non-empty collections
should just reflect that of the wrapped collection. Until now, using
NonEmptyList or NonEmptySet added a prefix — from now on, we treat
non-emptiness as simply a property of the collection, no different than other
such as their size, that are not reflected when turning into a string.
New arrow-core-result4k module.
Result4k
is a popular library for computation that may succeed or fail.
We now provide support for it as part of typed errors.
You can either consume them — that is, .bind() a Result value —
or produce them — use the result4k builder in a similar way to either.
Arrow Optics for Gradle, beta.
We have been working on a new approach to handle @optics annotations
with much less configuration, and that removes the need for manually
writing companion objects. This new approach is in beta,
read here all the details.
Migration to new plug-ins. Following our eager dependency update policy, we have moved to the new recommended plug-ins in the ecosystem.
- We now use KSP2,
 - Android now uses the Android Gradle Library Plugin for KMP,
 - Binary validation is done using the experimental built-in support,
 - We now publish a version catalog for consistent versioning of Arrow dependencies.
 - The Arrow plug-in for IntelliJ IDEs
now supports up to 2025.3, and understands code using context parameters
and the new 
RacingDSL.