0
# Collections and Data Structures
1
2
Type-safe collections that provide compile-time guarantees about their contents. Includes non-empty collections, validated containers, and functional collection operations that eliminate common runtime errors.
3
4
## Capabilities
5
6
### NonEmptyList
7
8
List guaranteed to contain at least one element, providing safe head access and eliminating empty list errors.
9
10
```kotlin { .api }
11
/**
12
* List with guaranteed non-empty contents
13
*/
14
data class NonEmptyList<out A>(
15
val head: A,
16
val tail: List<A>
17
) {
18
val size: Int
19
val indices: IntRange
20
}
21
22
/**
23
* Create NonEmptyList from head and tail elements
24
*/
25
fun <A> nonEmptyListOf(head: A, vararg tail: A): NonEmptyList<A>
26
27
/**
28
* Create NonEmptyList from single element
29
*/
30
fun <A> A.nel(): NonEmptyList<A>
31
```
32
33
**Usage Examples:**
34
35
```kotlin
36
// Safe construction
37
val numbers = nonEmptyListOf(1, 2, 3, 4, 5)
38
val single = 42.nel()
39
40
// Safe head access - no null checks needed
41
val first = numbers.head // Always safe: 1
42
val remaining = numbers.tail // [2, 3, 4, 5]
43
44
// Size is always >= 1
45
val count = numbers.size // 5
46
```
47
48
### NonEmptyList Transformations
49
50
Transform NonEmptyList values while preserving non-empty guarantee.
51
52
```kotlin { .api }
53
/**
54
* Transform each element, preserving non-empty structure
55
*/
56
fun <A, B> NonEmptyList<A>.map(f: (A) -> B): NonEmptyList<B>
57
58
/**
59
* Monadic bind for NonEmptyList
60
*/
61
fun <A, B> NonEmptyList<A>.flatMap(f: (A) -> NonEmptyList<B>): NonEmptyList<B>
62
63
/**
64
* Filter elements, may return empty list
65
*/
66
fun <A> NonEmptyList<A>.filter(predicate: (A) -> Boolean): List<A>
67
68
/**
69
* Filter elements, keeping only Some results
70
*/
71
fun <A, B> NonEmptyList<A>.mapNotNull(f: (A) -> B?): List<B>
72
73
/**
74
* Reverse the list order
75
*/
76
fun <A> NonEmptyList<A>.reverse(): NonEmptyList<A>
77
78
/**
79
* Remove duplicate elements
80
*/
81
fun <A> NonEmptyList<A>.distinct(): NonEmptyList<A>
82
```
83
84
**Usage Examples:**
85
86
```kotlin
87
val words = nonEmptyListOf("hello", "world", "arrow")
88
89
// Transform while preserving structure
90
val lengths = words.map { it.length } // NonEmptyList(5, 5, 5)
91
val uppercase = words.map { it.uppercase() } // NonEmptyList("HELLO", "WORLD", "ARROW")
92
93
// Flat mapping
94
val characters = words.flatMap { word ->
95
word.toCharArray().toList().toNonEmptyListOrNone().getOrElse { 'x'.nel() }
96
}
97
98
// Filtering (returns regular List since result might be empty)
99
val longWords = words.filter { it.length > 4 } // List("hello", "world", "arrow")
100
```
101
102
### NonEmptyList Folding
103
104
Reduce NonEmptyList to single values using fold operations.
105
106
```kotlin { .api }
107
/**
108
* Left-associative fold
109
*/
110
fun <A, B> NonEmptyList<A>.foldLeft(b: B, f: (B, A) -> B): B
111
112
/**
113
* Right-associative fold with lazy evaluation
114
*/
115
fun <A, B> NonEmptyList<A>.foldRight(
116
lb: Eval<B>,
117
f: (A, Eval<B>) -> Eval<B>
118
): Eval<B>
119
120
/**
121
* Reduce using the same type (no initial value needed)
122
*/
123
fun <A> NonEmptyList<A>.reduce(f: (A, A) -> A): A
124
```
125
126
### NonEmptyList Combination
127
128
Combine NonEmptyList instances while preserving non-empty guarantees.
129
130
```kotlin { .api }
131
/**
132
* Concatenate with another NonEmptyList
133
*/
134
fun <A> NonEmptyList<A>.plus(other: NonEmptyList<A>): NonEmptyList<A>
135
136
/**
137
* Concatenate with regular List
138
*/
139
fun <A> NonEmptyList<A>.plus(other: List<A>): NonEmptyList<A>
140
141
/**
142
* Append single element
143
*/
144
fun <A> NonEmptyList<A>.plus(element: A): NonEmptyList<A>
145
146
/**
147
* Prepend single element
148
*/
149
fun <A> NonEmptyList<A>.cons(element: A): NonEmptyList<A>
150
151
/**
152
* Zip with another NonEmptyList
153
*/
154
fun <A, B> NonEmptyList<A>.zip(other: NonEmptyList<B>): NonEmptyList<Pair<A, B>>
155
156
/**
157
* Zip with transformation function
158
*/
159
fun <A, B, C> NonEmptyList<A>.zip(
160
other: NonEmptyList<B>,
161
f: (A, B) -> C
162
): NonEmptyList<C>
163
```
164
165
### NonEmptyList Conversions
166
167
Convert between NonEmptyList and other collection types.
168
169
```kotlin { .api }
170
/**
171
* Convert to regular List
172
*/
173
fun <A> NonEmptyList<A>.toList(): List<A>
174
175
/**
176
* Convert List to NonEmptyList safely
177
*/
178
fun <A> List<A>.toNonEmptyListOrNull(): NonEmptyList<A>?
179
180
/**
181
* Convert List to Option<NonEmptyList>
182
*/
183
fun <A> List<A>.toNonEmptyListOrNone(): Option<NonEmptyList<A>>
184
```
185
186
**Usage Examples:**
187
188
```kotlin
189
val list1 = nonEmptyListOf(1, 2, 3)
190
val list2 = nonEmptyListOf(4, 5, 6)
191
192
// Combination
193
val combined = list1 + list2 // NonEmptyList(1, 2, 3, 4, 5, 6)
194
val withExtra = list1 + listOf(7, 8) // NonEmptyList(1, 2, 3, 7, 8)
195
val withSingle = list1 + 9 // NonEmptyList(1, 2, 3, 9)
196
197
// Zipping
198
val pairs = list1.zip(list2) // NonEmptyList(Pair(1,4), Pair(2,5), Pair(3,6))
199
val sums = list1.zip(list2) { a, b -> a + b } // NonEmptyList(5, 7, 9)
200
201
// Safe conversions
202
val regularList = listOf(1, 2, 3)
203
val maybeNel = regularList.toNonEmptyListOrNone() // Some(NonEmptyList(1, 2, 3))
204
205
val emptyList = emptyList<Int>()
206
val empty = emptyList.toNonEmptyListOrNull() // null
207
```
208
209
### NonEmptySet
210
211
Set guaranteed to contain at least one element.
212
213
```kotlin { .api }
214
/**
215
* Set with guaranteed non-empty contents
216
*/
217
data class NonEmptySet<out A>(
218
val head: A,
219
val tail: Set<A>
220
) {
221
val size: Int
222
}
223
224
/**
225
* Create NonEmptySet from head and tail elements
226
*/
227
fun <A> nonEmptySetOf(head: A, vararg tail: A): NonEmptySet<A>
228
```
229
230
### NonEmptySet Operations
231
232
Operations specific to NonEmptySet structure.
233
234
```kotlin { .api }
235
/**
236
* Check if element is contained in the set
237
*/
238
fun <A> NonEmptySet<A>.contains(element: A): Boolean
239
240
/**
241
* Add element to set (always returns NonEmptySet)
242
*/
243
fun <A> NonEmptySet<A>.plus(element: A): NonEmptySet<A>
244
245
/**
246
* Union with another NonEmptySet
247
*/
248
fun <A> NonEmptySet<A>.plus(other: NonEmptySet<A>): NonEmptySet<A>
249
250
/**
251
* Transform each element, preserving non-empty structure
252
*/
253
fun <A, B> NonEmptySet<A>.map(f: (A) -> B): NonEmptySet<B>
254
255
/**
256
* Monadic bind for NonEmptySet
257
*/
258
fun <A, B> NonEmptySet<A>.flatMap(f: (A) -> NonEmptySet<B>): NonEmptySet<B>
259
260
/**
261
* Convert to regular Set
262
*/
263
fun <A> NonEmptySet<A>.toSet(): Set<A>
264
```
265
266
**Usage Examples:**
267
268
```kotlin
269
val colors = nonEmptySetOf("red", "green", "blue")
270
271
// Safe operations
272
val hasRed = colors.contains("red") // true
273
val withYellow = colors + "yellow" // NonEmptySet("red", "green", "blue", "yellow")
274
275
// Transformations
276
val lengths = colors.map { it.length } // NonEmptySet(3, 5, 4)
277
val uppercased = colors.map { it.uppercase() } // NonEmptySet("RED", "GREEN", "BLUE")
278
```
279
280
### Collection Extensions
281
282
Extensions for working with standard Kotlin collections in functional ways.
283
284
```kotlin { .api }
285
/**
286
* Sequence a collection of Either values
287
*/
288
fun <E, A> Iterable<Either<E, A>>.sequence(): Either<E, List<A>>
289
290
/**
291
* Sequence a collection of Option values
292
*/
293
fun <A> Iterable<Option<A>>.sequence(): Option<List<A>>
294
295
/**
296
* Flatten collection of Either values, accumulating errors
297
*/
298
fun <E, A> Iterable<Either<E, A>>.flattenOrAccumulate(): Either<NonEmptyList<E>, List<A>>
299
300
/**
301
* Traverse collection with function returning Either
302
*/
303
fun <A, B, E> Iterable<A>.traverse(f: (A) -> Either<E, B>): Either<E, List<B>>
304
305
/**
306
* Traverse collection with function returning Option
307
*/
308
fun <A, B> Iterable<A>.traverse(f: (A) -> Option<B>): Option<List<B>>
309
```
310
311
**Usage Examples:**
312
313
```kotlin
314
// Sequence Either values
315
val results = listOf(1.right(), 2.right(), 3.right())
316
val sequenced = results.sequence() // Either.Right([1, 2, 3])
317
318
val mixed = listOf(1.right(), "error".left(), 3.right())
319
val failed = mixed.sequence() // Either.Left("error")
320
321
// Accumulate errors
322
val accumulated = mixed.flattenOrAccumulate() // Either.Left(NonEmptyList("error"))
323
324
// Traverse with parsing
325
val strings = listOf("1", "2", "3")
326
val parsed = strings.traverse { s ->
327
Either.catch { s.toInt() }.mapLeft { "Parse error: $s" }
328
} // Either.Right([1, 2, 3])
329
```
330
331
## Type Aliases
332
333
```kotlin { .api }
334
/**
335
* Shorter alias for NonEmptyList
336
*/
337
typealias Nel<A> = NonEmptyList<A>
338
339
/**
340
* Shorter alias for NonEmptySet
341
*/
342
typealias Nes<A> = NonEmptySet<A>
343
```