Functional companion to Kotlin's Standard Library providing core data types and error handling
npx @tessl/cli install tessl/maven-io-arrow-kt--arrow-core@1.2.0Arrow Core is a comprehensive functional programming library for Kotlin that provides a lingua franca of interfaces and abstractions across Kotlin libraries. It serves as the foundation for typed functional programming in Kotlin, offering high-level abstractions for error handling, data transformation, and computation composition that seamlessly integrate across different Kotlin platforms including JVM, Android, JavaScript, and Native targets.
implementation("io.arrow-kt:arrow-core:1.2.4")import arrow.core.*
import arrow.core.raise.*For specific types:
import arrow.core.Either
import arrow.core.Option
import arrow.core.NonEmptyList
import arrow.core.raise.either
import arrow.core.raise.optionimport arrow.core.*
import arrow.core.raise.*
// Type-safe error handling with Either
val result: Either<String, Int> = either {
val x = parseNumber("42").bind() // Extract success or raise error
val y = parseNumber("24").bind()
x + y
}
// Optional values with Option
val user: Option<User> = findUser(id).map { it.copy(active = true) }
// Non-empty collections
val items = nonEmptyListOf("first", "second", "third")
val processed = items.map { it.uppercase() }
fun parseNumber(s: String): Either<String, Int> =
Either.catch { s.toInt() }.mapLeft { "Invalid number: $s" }Arrow Core is built around several key design principles:
Type-safe error handling that makes failure cases explicit and composable. Either is right-biased, treating success (Right) as the default path and providing extensive combinators for error handling.
sealed class Either<out A, out B> {
data class Left<out A>(val value: A) : Either<A, Nothing>()
data class Right<out B>(val value: B) : Either<Nothing, B>()
companion object {
fun <A, B> Right(value: B): Either<A, B>
fun <A, B> Left(value: A): Either<A, B>
fun <R> catch(f: () -> R): Either<Throwable, R>
fun <reified T : Throwable, R> catchOrThrow(f: () -> R): Either<T, R>
// zipOrAccumulate methods for error accumulation
fun <E, A, B, Z> zipOrAccumulate(
combine: (E, E) -> E,
a: Either<E, A>,
b: Either<E, B>,
transform: (A, B) -> Z
): Either<E, Z>
fun <E, A, B, Z> zipOrAccumulate(
a: Either<E, A>,
b: Either<E, B>,
transform: (A, B) -> Z
): Either<NonEmptyList<E>, Z>
// Additional overloads for 3-10 parameters available
}
}Safe handling of optional values without null pointer exceptions. Option provides a type-safe alternative to nullable types with comprehensive functional operations.
sealed class Option<out A> {
object None : Option<Nothing>()
data class Some<out A>(val value: A) : Option<A>()
companion object {
fun <A> fromNullable(value: A?): Option<A>
}
}Modern DSL for typed error handling using structured concurrency patterns. Raise provides ergonomic builders that eliminate boilerplate while maintaining type safety.
interface Raise<in Error> {
@RaiseDSL
fun raise(r: Error): Nothing
@RaiseDSL
fun ensure(condition: Boolean, raise: () -> Error)
}
fun <Error, A> either(block: Raise<Error>.() -> A): Either<Error, A>
fun <A> option(block: OptionRaise.() -> A): Option<A>Type-safe collections that provide compile-time guarantees about their contents. Includes non-empty collections, validated containers, and functional collection operations.
data class NonEmptyList<out A>(val head: A, val tail: List<A>)
data class NonEmptySet<out A>(val head: A, val tail: Set<A>)
fun <A> nonEmptyListOf(head: A, vararg tail: A): NonEmptyList<A>
fun <A> nonEmptySetOf(head: A, vararg tail: A): NonEmptySet<A>Represents values that can be either one type, another type, or both simultaneously. Useful for computations that can produce partial results alongside errors or warnings.
sealed interface Ior<out A, out B> {
data class Left<out A>(val value: A) : Ior<A, Nothing>
data class Right<out B>(val value: B) : Ior<Nothing, B>
data class Both<out A, out B>(val left: A, val right: B) : Ior<A, B>
}Comprehensive utilities for function composition, currying, memoization, and other functional programming patterns. Provides building blocks for higher-order functional programming.
fun <A> identity(a: A): A
fun <A, B, C> ((B) -> C).compose(f: (A) -> B): (A) -> C
fun <A, B> ((A) -> B).memoize(): (A) -> Btypealias Nel<A> = NonEmptyList<A>
typealias EitherNel<E, A> = Either<NonEmptyList<E>, A>
typealias IorNel<E, A> = Ior<NonEmptyList<E>, A>data class Tuple4<out A, out B, out C, out D>(
val first: A,
val second: B,
val third: C,
val fourth: D
)
// Similar definitions for Tuple5 through Tuple22sealed class Eval<out A> {
abstract fun value(): A
companion object {
fun <A> now(value: A): Eval<A>
fun <A> later(f: () -> A): Eval<A>
fun <A> always(f: () -> A): Eval<A>
}
}