or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

collections.mderror-handling.mdfunctional-utilities.mdinclusive-or.mdindex.mdoptional-values.mdraise-dsl.md

collections.mddocs/

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

```