Functional companion to Kotlin's Standard Library providing type-safe error handling and functional programming constructs for iOS x64 target
—
Arrow Core provides various utility functions, extensions, and type aliases that enhance Kotlin's standard library with functional programming patterns.
// Identity function - returns input unchanged
fun <A> identity(a: A): A
// Constant function - returns constant value regardless of input
fun <P1, T> constant(t: T): (P1) -> T// Escape special characters in strings
fun String.escaped(): String // Escapes \n, \r, \", \', \t, \b// FlatMap for Result type
fun <A, B> Result<A>.flatMap(transform: (value: A) -> Result<B>): Result<B>// Functional type aliases
typealias Predicate<T> = (T) -> Boolean
typealias Nel<A> = NonEmptyList<A>
typealias EitherNel<E, A> = Either<NonEmptyList<E>, A>
typealias IorNel<A, B> = Ior<Nel<A>, B>// Map predicate to work with nullable values
fun <T : Any> Predicate<T>.mapNullable(): (T?) -> Boolean// Internal optimization object for performance
object EmptyValue {
fun <A> unbox(value: Any?): A
fun <T> combine(first: Any?, second: T, combine: (T, T) -> T): T
fun <T, R> fold(value: Any?, ifEmpty: () -> R, ifNotEmpty: (T) -> R): R
}// Build larger tuples from smaller ones
operator fun <A, B, C> Pair<A, B>.plus(c: C): Triple<A, B, C>
operator fun <A, B, C, D> Triple<A, B, C>.plus(d: D): Tuple4<A, B, C, D>
operator fun <A, B, C, D, E> Tuple4<A, B, C, D>.plus(e: E): Tuple5<A, B, C, D, E>
operator fun <A, B, C, D, E, F> Tuple5<A, B, C, D, E>.plus(f: F): Tuple6<A, B, C, D, E, F>
operator fun <A, B, C, D, E, F, G> Tuple6<A, B, C, D, E, F>.plus(g: G): Tuple7<A, B, C, D, E, F, G>
operator fun <A, B, C, D, E, F, G, H> Tuple7<A, B, C, D, E, F, G>.plus(h: H): Tuple8<A, B, C, D, E, F, G, H>
operator fun <A, B, C, D, E, F, G, H, I> Tuple8<A, B, C, D, E, F, G, H>.plus(i: I): Tuple9<A, B, C, D, E, F, G, H, I>// Lexicographic comparison for Pair and Triple
operator fun <A : Comparable<A>, B : Comparable<B>> Pair<A, B>.compareTo(other: Pair<A, B>): Int
operator fun <A : Comparable<A>, B : Comparable<B>, C : Comparable<C>> Triple<A, B, C>.compareTo(other: Triple<A, B, C>): Int
// Iterable comparison
operator fun <A : Comparable<A>> Iterable<A>.compareTo(other: Iterable<A>): Intimport arrow.core.*
// Identity function - useful in higher-order functions
val numbers = listOf(1, 2, 3, 4, 5)
val unchanged = numbers.map(::identity) // [1, 2, 3, 4, 5]
// Constant function - always returns the same value
val alwaysTrue = constant<String, Boolean>(true)
val results = listOf("hello", "world").map(alwaysTrue) // [true, true]
// Useful in conditional operations
val defaultValue = constant<Any?, String>("default")
val values = listOf(null, "actual").map { it ?: defaultValue(it) } // ["default", "actual"]import arrow.core.*
// Escape special characters
val rawString = "Hello\nWorld\t\"quoted\""
val escaped = rawString.escaped()
// Result: "Hello\\nWorld\\t\\\"quoted\\\""
// Useful for logging or JSON output
val logMessage = "User input: ${userInput.escaped()}"
val jsonValue = "\"${rawValue.escaped()}\""import arrow.core.*
// Chain Result operations
fun parseNumber(input: String): Result<Int> = runCatching { input.toInt() }
fun validatePositive(number: Int): Result<Int> =
if (number > 0) Result.success(number) else Result.failure(IllegalArgumentException("Must be positive"))
fun processInput(input: String): Result<Int> =
parseNumber(input).flatMap { number ->
validatePositive(number)
}
val valid = processInput("42") // Success(42)
val invalid = processInput("-5") // Failure(IllegalArgumentException)
val error = processInput("abc") // Failure(NumberFormatException)import arrow.core.*
// Build tuples incrementally
val name = "Alice" to "Smith" // Pair<String, String>
val withAge = name + 25 // Triple<String, String, Int>
val withCity = withAge + "NYC" // Tuple4<String, String, Int, String>
val withJob = withCity + "Engineer" // Tuple5<String, String, Int, String, String>
// Chain operations
val coordinates = 10 to 20
val point3D = coordinates + 30
val withLabel = point3D + "origin"
val withTimestamp = withLabel + System.currentTimeMillis()
// Result: Tuple5<Int, Int, Int, String, Long>
// Useful for building complex data structures
fun buildUserProfile(name: String, age: Int): Tuple9<String, Int, String, String, Boolean, Long, String, String, String> {
return name to age +
"Unknown City" +
"Unknown Job" +
true +
System.currentTimeMillis() +
"Active" +
"Standard" +
"No notes"
}import arrow.core.*
// Work with predicates
val isEven: Predicate<Int> = { it % 2 == 0 }
val isPositive: Predicate<Int> = { it > 0 }
val numbers = listOf(1, 2, 3, 4, 5, 6)
val evenNumbers = numbers.filter(isEven) // [2, 4, 6]
val positiveNumbers = numbers.filter(isPositive) // [1, 2, 3, 4, 5, 6]
// Map to work with nullable values
val nullableIsEven = isEven.mapNullable()
val nullableNumbers = listOf(1, null, 2, null, 3)
val results = nullableNumbers.map(nullableIsEven) // [false, false, true, false, false]import arrow.core.*
// Use convenient type aliases
fun validateUsers(users: List<String>): EitherNel<String, List<String>> {
val errors = mutableListOf<String>()
val validUsers = users.filter { user ->
when {
user.isBlank() -> {
errors.add("Empty user name")
false
}
user.length < 2 -> {
errors.add("User name too short: $user")
false
}
else -> true
}
}
return if (errors.isEmpty()) {
validUsers.right()
} else {
errors.toNonEmptyListOrNull()!!.left()
}
}
// Use Nel alias for conciseness
fun processItems(items: Nel<String>): String {
return "Processing ${items.size} items starting with '${items.head}'"
}
// Use IorNel for partial results with warnings
fun validateWithWarnings(input: String): IorNel<String, String> {
val warnings = mutableListOf<String>()
if (input.startsWith(" ") || input.endsWith(" ")) {
warnings.add("Input has leading or trailing whitespace")
}
val cleaned = input.trim()
return if (cleaned.isEmpty()) {
listOf("Input is empty after trimming").toNonEmptyListOrNull()!!.leftIor()
} else if (warnings.isNotEmpty()) {
Ior.Both(warnings.toNonEmptyListOrNull()!!, cleaned)
} else {
cleaned.rightIor()
}
}import arrow.core.*
// Compare pairs lexicographically
val pairs = listOf(
"apple" to 10,
"banana" to 5,
"apple" to 15,
"cherry" to 3
)
val sorted = pairs.sorted()
// Result: [("apple", 10), ("apple", 15), ("banana", 5), ("cherry", 3)]
// Compare triples
val coordinates = listOf(
Triple(1, 2, 3),
Triple(1, 1, 4),
Triple(2, 1, 1),
Triple(1, 2, 2)
)
val sortedCoords = coordinates.sorted()
// Result: [(1, 1, 4), (1, 2, 2), (1, 2, 3), (2, 1, 1)]
// Compare iterables
val lists = listOf(
listOf(1, 2, 3),
listOf(1, 2),
listOf(1, 3),
listOf(1, 2, 4)
)
val sortedLists = lists.sorted()
// Result: [[1, 2], [1, 2, 3], [1, 2, 4], [1, 3]]Install with Tessl CLI
npx tessl i tessl/maven-io-arrow-kt--arrow-core-iosx64