or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

collection-extensions.mderror-handling.mdindex.mdoptional-values.mdpartial-results.mdproduct-types.mdraise-dsl.mdsafe-collections.mdutility-functions.md

utility-functions.mddocs/

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

```