0
# Utility Functions
1
2
Arrow Core provides various utility functions, extensions, and type aliases that enhance Kotlin's standard library with functional programming patterns.
3
4
## Core Utility Functions
5
6
```kotlin { .api }
7
// Identity function - returns input unchanged
8
fun <A> identity(a: A): A
9
10
// Constant function - returns constant value regardless of input
11
fun <P1, T> constant(t: T): (P1) -> T
12
```
13
14
## String Extensions
15
16
```kotlin { .api }
17
// Escape special characters in strings
18
fun String.escaped(): String // Escapes \n, \r, \", \', \t, \b
19
```
20
21
## Result Extensions
22
23
```kotlin { .api }
24
// FlatMap for Result type
25
fun <A, B> Result<A>.flatMap(transform: (value: A) -> Result<B>): Result<B>
26
```
27
28
## Type Aliases
29
30
```kotlin { .api }
31
// Functional type aliases
32
typealias Predicate<T> = (T) -> Boolean
33
typealias Nel<A> = NonEmptyList<A>
34
typealias EitherNel<E, A> = Either<NonEmptyList<E>, A>
35
typealias IorNel<A, B> = Ior<Nel<A>, B>
36
```
37
38
## Predicate Extensions
39
40
```kotlin { .api }
41
// Map predicate to work with nullable values
42
fun <T : Any> Predicate<T>.mapNullable(): (T?) -> Boolean
43
```
44
45
## Internal Optimization Utilities
46
47
```kotlin { .api }
48
// Internal optimization object for performance
49
object EmptyValue {
50
fun <A> unbox(value: Any?): A
51
fun <T> combine(first: Any?, second: T, combine: (T, T) -> T): T
52
fun <T, R> fold(value: Any?, ifEmpty: () -> R, ifNotEmpty: (T) -> R): R
53
}
54
```
55
56
## Tuple Building Operations
57
58
```kotlin { .api }
59
// Build larger tuples from smaller ones
60
operator fun <A, B, C> Pair<A, B>.plus(c: C): Triple<A, B, C>
61
operator fun <A, B, C, D> Triple<A, B, C>.plus(d: D): Tuple4<A, B, C, D>
62
operator fun <A, B, C, D, E> Tuple4<A, B, C, D>.plus(e: E): Tuple5<A, B, C, D, E>
63
operator fun <A, B, C, D, E, F> Tuple5<A, B, C, D, E>.plus(f: F): Tuple6<A, B, C, D, E, F>
64
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>
65
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>
66
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>
67
```
68
69
## Comparison Extensions
70
71
```kotlin { .api }
72
// Lexicographic comparison for Pair and Triple
73
operator fun <A : Comparable<A>, B : Comparable<B>> Pair<A, B>.compareTo(other: Pair<A, B>): Int
74
operator fun <A : Comparable<A>, B : Comparable<B>, C : Comparable<C>> Triple<A, B, C>.compareTo(other: Triple<A, B, C>): Int
75
76
// Iterable comparison
77
operator fun <A : Comparable<A>> Iterable<A>.compareTo(other: Iterable<A>): Int
78
```
79
80
## Usage Examples
81
82
### Identity and Constant Functions
83
84
```kotlin
85
import arrow.core.*
86
87
// Identity function - useful in higher-order functions
88
val numbers = listOf(1, 2, 3, 4, 5)
89
val unchanged = numbers.map(::identity) // [1, 2, 3, 4, 5]
90
91
// Constant function - always returns the same value
92
val alwaysTrue = constant<String, Boolean>(true)
93
val results = listOf("hello", "world").map(alwaysTrue) // [true, true]
94
95
// Useful in conditional operations
96
val defaultValue = constant<Any?, String>("default")
97
val values = listOf(null, "actual").map { it ?: defaultValue(it) } // ["default", "actual"]
98
```
99
100
### String Escaping
101
102
```kotlin
103
import arrow.core.*
104
105
// Escape special characters
106
val rawString = "Hello\nWorld\t\"quoted\""
107
val escaped = rawString.escaped()
108
// Result: "Hello\\nWorld\\t\\\"quoted\\\""
109
110
// Useful for logging or JSON output
111
val logMessage = "User input: ${userInput.escaped()}"
112
val jsonValue = "\"${rawValue.escaped()}\""
113
```
114
115
### Result FlatMap
116
117
```kotlin
118
import arrow.core.*
119
120
// Chain Result operations
121
fun parseNumber(input: String): Result<Int> = runCatching { input.toInt() }
122
fun validatePositive(number: Int): Result<Int> =
123
if (number > 0) Result.success(number) else Result.failure(IllegalArgumentException("Must be positive"))
124
125
fun processInput(input: String): Result<Int> =
126
parseNumber(input).flatMap { number ->
127
validatePositive(number)
128
}
129
130
val valid = processInput("42") // Success(42)
131
val invalid = processInput("-5") // Failure(IllegalArgumentException)
132
val error = processInput("abc") // Failure(NumberFormatException)
133
```
134
135
### Tuple Building
136
137
```kotlin
138
import arrow.core.*
139
140
// Build tuples incrementally
141
val name = "Alice" to "Smith" // Pair<String, String>
142
val withAge = name + 25 // Triple<String, String, Int>
143
val withCity = withAge + "NYC" // Tuple4<String, String, Int, String>
144
val withJob = withCity + "Engineer" // Tuple5<String, String, Int, String, String>
145
146
// Chain operations
147
val coordinates = 10 to 20
148
val point3D = coordinates + 30
149
val withLabel = point3D + "origin"
150
val withTimestamp = withLabel + System.currentTimeMillis()
151
// Result: Tuple5<Int, Int, Int, String, Long>
152
153
// Useful for building complex data structures
154
fun buildUserProfile(name: String, age: Int): Tuple9<String, Int, String, String, Boolean, Long, String, String, String> {
155
return name to age +
156
"Unknown City" +
157
"Unknown Job" +
158
true +
159
System.currentTimeMillis() +
160
"Active" +
161
"Standard" +
162
"No notes"
163
}
164
```
165
166
### Predicate Operations
167
168
```kotlin
169
import arrow.core.*
170
171
// Work with predicates
172
val isEven: Predicate<Int> = { it % 2 == 0 }
173
val isPositive: Predicate<Int> = { it > 0 }
174
175
val numbers = listOf(1, 2, 3, 4, 5, 6)
176
val evenNumbers = numbers.filter(isEven) // [2, 4, 6]
177
val positiveNumbers = numbers.filter(isPositive) // [1, 2, 3, 4, 5, 6]
178
179
// Map to work with nullable values
180
val nullableIsEven = isEven.mapNullable()
181
val nullableNumbers = listOf(1, null, 2, null, 3)
182
val results = nullableNumbers.map(nullableIsEven) // [false, false, true, false, false]
183
```
184
185
### Type Aliases Usage
186
187
```kotlin
188
import arrow.core.*
189
190
// Use convenient type aliases
191
fun validateUsers(users: List<String>): EitherNel<String, List<String>> {
192
val errors = mutableListOf<String>()
193
val validUsers = users.filter { user ->
194
when {
195
user.isBlank() -> {
196
errors.add("Empty user name")
197
false
198
}
199
user.length < 2 -> {
200
errors.add("User name too short: $user")
201
false
202
}
203
else -> true
204
}
205
}
206
207
return if (errors.isEmpty()) {
208
validUsers.right()
209
} else {
210
errors.toNonEmptyListOrNull()!!.left()
211
}
212
}
213
214
// Use Nel alias for conciseness
215
fun processItems(items: Nel<String>): String {
216
return "Processing ${items.size} items starting with '${items.head}'"
217
}
218
219
// Use IorNel for partial results with warnings
220
fun validateWithWarnings(input: String): IorNel<String, String> {
221
val warnings = mutableListOf<String>()
222
223
if (input.startsWith(" ") || input.endsWith(" ")) {
224
warnings.add("Input has leading or trailing whitespace")
225
}
226
227
val cleaned = input.trim()
228
229
return if (cleaned.isEmpty()) {
230
listOf("Input is empty after trimming").toNonEmptyListOrNull()!!.leftIor()
231
} else if (warnings.isNotEmpty()) {
232
Ior.Both(warnings.toNonEmptyListOrNull()!!, cleaned)
233
} else {
234
cleaned.rightIor()
235
}
236
}
237
```
238
239
### Comparison Operations
240
241
```kotlin
242
import arrow.core.*
243
244
// Compare pairs lexicographically
245
val pairs = listOf(
246
"apple" to 10,
247
"banana" to 5,
248
"apple" to 15,
249
"cherry" to 3
250
)
251
252
val sorted = pairs.sorted()
253
// Result: [("apple", 10), ("apple", 15), ("banana", 5), ("cherry", 3)]
254
255
// Compare triples
256
val coordinates = listOf(
257
Triple(1, 2, 3),
258
Triple(1, 1, 4),
259
Triple(2, 1, 1),
260
Triple(1, 2, 2)
261
)
262
263
val sortedCoords = coordinates.sorted()
264
// Result: [(1, 1, 4), (1, 2, 2), (1, 2, 3), (2, 1, 1)]
265
266
// Compare iterables
267
val lists = listOf(
268
listOf(1, 2, 3),
269
listOf(1, 2),
270
listOf(1, 3),
271
listOf(1, 2, 4)
272
)
273
274
val sortedLists = lists.sorted()
275
// Result: [[1, 2], [1, 2, 3], [1, 2, 4], [1, 3]]
276
```