or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

collections.mdconcurrent.mdcontrol-types.mdcore-types.mdfunctional-interfaces.mdindex.md

control-types.mddocs/

0

# Control Types

1

2

Monadic control structures for error handling, optional values, and validation that eliminate null pointer exceptions and provide functional composition patterns.

3

4

## Capabilities

5

6

### Option - Optional Values

7

8

Container for values that may or may not exist, eliminating null pointer exceptions with functional composition.

9

10

```java { .api }

11

/**

12

* Container for optional values - either Some(value) or None

13

*/

14

interface Option<T> extends Value<T> {

15

// Factory methods

16

static <T> Option<T> of(T value); // Create Some(value) or None if value is null

17

static <T> Option<T> some(T value); // Create Some(value), throws if null

18

static <T> Option<T> none(); // Create None instance

19

static <T> Option<T> when(boolean condition, T value); // Conditional creation

20

static <T> Option<T> when(boolean condition, Supplier<? extends T> supplier);

21

22

// State checking

23

boolean isDefined(); // true if Some, false if None

24

boolean isEmpty(); // true if None, false if Some

25

26

// Value access

27

T get(); // Get value, throws if None

28

T getOrElse(T other); // Get value or return other if None

29

T getOrElse(Supplier<? extends T> supplier); // Get value or compute other if None

30

<X extends Throwable> T getOrElseThrow(Supplier<X> exceptionSupplier) throws X;

31

Option<T> orElse(Option<? extends T> other); // Return this if Some, other if None

32

Option<T> orElse(Supplier<? extends Option<? extends T>> supplier);

33

34

// Transformation operations

35

<U> Option<U> map(Function<? super T, ? extends U> mapper);

36

<U> Option<U> flatMap(Function<? super T, ? extends Option<? extends U>> mapper);

37

Option<T> filter(Predicate<? super T> predicate);

38

Option<T> filterNot(Predicate<? super T> predicate);

39

40

// Side effects

41

Option<T> peek(Consumer<? super T> action); // Perform action if Some

42

43

// Conversion operations

44

Either<Throwable, T> toEither();

45

Try<T> toTry();

46

List<T> toList(); // Empty list if None, single-element if Some

47

java.util.Optional<T> toJavaOptional();

48

49

// Combining operations

50

<U> Option<Tuple2<T, U>> zip(Option<? extends U> that);

51

<U, R> Option<R> zipWith(Option<? extends U> that, BiFunction<? super T, ? super U, ? extends R> mapper);

52

}

53

54

/**

55

* Some variant containing a value

56

*/

57

class Some<T> implements Option<T> {

58

T get(); // Returns the contained value

59

}

60

61

/**

62

* None variant representing absence of value

63

*/

64

class None<T> implements Option<T> {

65

static None<Object> instance(); // Singleton None instance

66

}

67

```

68

69

**Usage Examples:**

70

71

```java

72

import io.vavr.control.Option;

73

74

// Creating Options

75

Option<String> some = Option.of("Hello");

76

Option<String> none = Option.of(null); // Creates None

77

Option<Integer> conditional = Option.when(5 > 3, 42); // Creates Some(42)

78

79

// Safe operations

80

String result = some

81

.map(String::toUpperCase)

82

.filter(s -> s.length() > 3)

83

.getOrElse("DEFAULT");

84

85

// Chaining operations

86

Option<Integer> length = some.map(String::length);

87

Option<String> doubled = some.flatMap(s ->

88

s.isEmpty() ? Option.none() : Option.some(s + s));

89

90

// Pattern matching style

91

String describe = some.fold(

92

() -> "No value",

93

value -> "Value: " + value

94

);

95

96

// Converting to other types

97

java.util.Optional<String> javaOpt = some.toJavaOptional();

98

List<String> list = some.toList(); // [Hello] or empty list

99

100

// Combining Options

101

Option<String> firstName = Option.of("John");

102

Option<String> lastName = Option.of("Doe");

103

Option<String> fullName = firstName.zipWith(lastName, (f, l) -> f + " " + l);

104

```

105

106

### Either - Disjoint Union

107

108

Represents a value that can be one of two types - typically used for error handling where Left represents error and Right represents success.

109

110

```java { .api }

111

/**

112

* Disjoint union type - either Left(error) or Right(value)

113

*/

114

interface Either<L, R> extends Value<R> {

115

// Factory methods

116

static <L, R> Either<L, R> left(L left); // Create Left instance

117

static <L, R> Either<L, R> right(R right); // Create Right instance

118

static <L, R> Either<L, R> cond(boolean test, R right, L left); // Conditional creation

119

120

// State checking

121

boolean isLeft(); // true if Left, false if Right

122

boolean isRight(); // true if Right, false if Left

123

124

// Value access

125

R get(); // Get right value, throws if Left

126

L getLeft(); // Get left value, throws if Right

127

R getOrElseGet(Function<? super L, ? extends R> other); // Get right or compute from left

128

L getLeftOrElseGet(Function<? super R, ? extends L> other); // Get left or compute from right

129

<X extends Throwable> R getOrElseThrow(Function<? super L, X> exceptionFunction) throws X;

130

void orElseRun(Consumer<? super L> action); // Run action if Left

131

132

// Alternative operations

133

Either<L, R> orElse(Either<? extends L, ? extends R> other); // Use other if Left

134

Either<L, R> orElse(Supplier<? extends Either<? extends L, ? extends R>> supplier);

135

136

// Transformation operations

137

<U> Either<L, U> map(Function<? super R, ? extends U> mapper); // Transform right value

138

<U> Either<U, R> mapLeft(Function<? super L, ? extends U> leftMapper); // Transform left value

139

<L2, R2> Either<L2, R2> bimap(Function<? super L, ? extends L2> leftMapper,

140

Function<? super R, ? extends R2> rightMapper);

141

142

<U> Either<L, U> flatMap(Function<? super R, ? extends Either<L, ? extends U>> mapper);

143

144

// Filtering

145

Option<Either<L, R>> filter(Predicate<? super R> predicate);

146

Option<Either<L, R>> filterOrElse(Predicate<? super R> predicate, L zero);

147

148

// Side effects

149

Either<L, R> peek(Consumer<? super R> action); // Perform action if Right

150

Either<L, R> peekLeft(Consumer<? super L> action); // Perform action if Left

151

152

// Swapping and projections

153

Either<R, L> swap(); // Swap Left and Right

154

LeftProjection<L, R> left(); // Project to Left operations

155

RightProjection<L, R> right(); // Project to Right operations

156

157

// Folding operations

158

<U> U fold(Function<? super L, ? extends U> leftMapper,

159

Function<? super R, ? extends U> rightMapper);

160

161

// Conversion operations

162

Option<R> toOption(); // Right becomes Some, Left becomes None

163

Try<R> toTry(); // Assumes Left contains Throwable

164

Validation<L, R> toValidation();

165

}

166

167

/**

168

* Left variant containing error/left value

169

*/

170

class Left<L, R> implements Either<L, R> {

171

L getLeft(); // Returns the left value

172

}

173

174

/**

175

* Right variant containing success/right value

176

*/

177

class Right<L, R> implements Either<L, R> {

178

R get(); // Returns the right value

179

}

180

181

/**

182

* Left projection for operating on left values

183

*/

184

class LeftProjection<L, R> {

185

<U> Either<U, R> map(Function<? super L, ? extends U> mapper);

186

<U> Either<U, R> flatMap(Function<? super L, ? extends Either<? extends U, R>> mapper);

187

Option<L> filter(Predicate<? super L> predicate);

188

L getOrElseGet(Function<? super R, ? extends L> other);

189

}

190

191

/**

192

* Right projection for operating on right values

193

*/

194

class RightProjection<L, R> {

195

<U> Either<L, U> map(Function<? super R, ? extends U> mapper);

196

<U> Either<L, U> flatMap(Function<? super R, ? extends Either<L, ? extends U>> mapper);

197

Option<R> filter(Predicate<? super R> predicate);

198

R getOrElseGet(Function<? super L, ? extends R> other);

199

}

200

```

201

202

**Usage Examples:**

203

204

```java

205

import io.vavr.control.Either;

206

207

// Creating Either instances

208

Either<String, Integer> success = Either.right(42);

209

Either<String, Integer> failure = Either.left("Error occurred");

210

211

// Error handling pattern

212

Either<String, String> result = parseInteger("123")

213

.map(i -> "Parsed: " + i)

214

.mapLeft(error -> "Failed: " + error);

215

216

// Chaining operations (right-biased)

217

Either<String, Integer> doubled = success

218

.flatMap(value -> value > 0 ? Either.right(value * 2) : Either.left("Negative number"));

219

220

// Folding both sides

221

String message = result.fold(

222

error -> "Error: " + error,

223

value -> "Success: " + value

224

);

225

226

// Working with projections

227

String leftResult = failure.left().map(String::toUpperCase).getOrElseGet(i -> "No error");

228

Integer rightResult = success.right().map(i -> i + 1).getOrElseGet(err -> 0);

229

230

// Converting between types

231

Option<Integer> opt = success.toOption(); // Some(42) if Right, None if Left

232

Try<Integer> attempt = success.toTry(); // Success(42) if Right, Failure if Left

233

234

// Helper method example

235

static Either<String, Integer> parseInteger(String str) {

236

try {

237

return Either.right(Integer.parseInt(str));

238

} catch (NumberFormatException e) {

239

return Either.left("Invalid number: " + str);

240

}

241

}

242

```

243

244

### Try - Exception Handling

245

246

Represents a computation that may succeed with a value or fail with an exception, providing functional exception handling.

247

248

```java { .api }

249

/**

250

* Computation that may succeed or fail - either Success(value) or Failure(exception)

251

*/

252

interface Try<T> extends Value<T> {

253

// Factory methods

254

static <T> Try<T> of(CheckedFunction0<? extends T> supplier); // Try computation

255

static <T> Try<T> success(T value); // Create Success

256

static <T> Try<T> failure(Throwable exception); // Create Failure

257

static <T> Try<T> withResources(CheckedFunction0<? extends T> supplier,

258

AutoCloseable... closeables); // Try-with-resources

259

260

// State checking

261

boolean isSuccess(); // true if Success, false if Failure

262

boolean isFailure(); // true if Failure, false if Success

263

264

// Value access

265

T get(); // Get value, throws if Failure

266

T getOrElse(T other); // Get value or return other if Failure

267

T getOrElse(Supplier<? extends T> supplier);

268

<X extends Throwable> T getOrElseThrow(Function<? super Throwable, X> f) throws X;

269

270

// Exception access (for Failure)

271

Throwable getCause(); // Get exception, throws if Success

272

273

// Transformation operations

274

<U> Try<U> map(Function<? super T, ? extends U> mapper);

275

<U> Try<U> mapTry(CheckedFunction1<? super T, ? extends U> mapper);

276

<U> Try<U> flatMap(Function<? super T, ? extends Try<? extends U>> mapper);

277

<U> Try<U> flatMapTry(CheckedFunction1<? super T, ? extends Try<? extends U>> mapper);

278

279

// Error handling

280

Try<T> recover(Function<? super Throwable, ? extends T> recovery);

281

Try<T> recoverWith(Function<? super Throwable, ? extends Try<? extends T>> recovery);

282

Try<T> mapFailure(Function<? super Throwable, ? extends Throwable> f);

283

284

// Filtering

285

Try<T> filter(Predicate<? super T> predicate);

286

Try<T> filterTry(CheckedPredicate<? super T> predicate);

287

288

// Side effects

289

Try<T> peek(Consumer<? super T> action); // Perform action if Success

290

Try<T> onFailure(Consumer<? super Throwable> action); // Perform action if Failure

291

292

// Conversion operations

293

Either<Throwable, T> toEither(); // Failure -> Left, Success -> Right

294

Option<T> toOption(); // Failure -> None, Success -> Some

295

Validation<Throwable, T> toValidation();

296

297

// Folding operations

298

<U> U fold(Function<? super Throwable, ? extends U> failureMapper,

299

Function<? super T, ? extends U> successMapper);

300

301

// Combining operations

302

<U> Try<Tuple2<T, U>> zip(Try<? extends U> that);

303

<U, R> Try<R> zipWith(Try<? extends U> that, BiFunction<? super T, ? super U, ? extends R> mapper);

304

}

305

306

/**

307

* Success variant containing the computed value

308

*/

309

class Success<T> implements Try<T> {

310

T get(); // Returns the successful value

311

}

312

313

/**

314

* Failure variant containing the exception

315

*/

316

class Failure<T> implements Try<T> {

317

Throwable getCause(); // Returns the exception

318

}

319

```

320

321

**Usage Examples:**

322

323

```java

324

import io.vavr.control.Try;

325

import io.vavr.CheckedFunction1;

326

327

// Basic Try operations

328

Try<Integer> result = Try.of(() -> Integer.parseInt("123"));

329

Try<Integer> failure = Try.of(() -> Integer.parseInt("abc"));

330

331

// Chaining operations

332

Try<String> processed = result

333

.map(i -> i * 2)

334

.map(i -> "Result: " + i)

335

.recover(ex -> "Error: " + ex.getMessage());

336

337

// Exception handling

338

Try<String> safe = Try.of(() -> riskyOperation())

339

.recover(throwable -> "Default value")

340

.map(String::toUpperCase);

341

342

// Filtering with exceptions

343

Try<Integer> positive = result.filter(i -> i > 0); // Becomes Failure if <= 0

344

345

// Working with multiple Try instances

346

Try<String> name = Try.of(() -> getName());

347

Try<Integer> age = Try.of(() -> getAge());

348

Try<String> person = name.zipWith(age, (n, a) -> n + " is " + a + " years old");

349

350

// Try-with-resources pattern

351

Try<String> content = Try.withResources(

352

() -> Files.lines(Paths.get("file.txt")).collect(Collectors.joining("\n")),

353

Files.newBufferedReader(Paths.get("file.txt"))

354

);

355

356

// Converting to other types

357

Option<Integer> opt = result.toOption(); // Some(123) or None

358

Either<Throwable, Integer> either = result.toEither(); // Right(123) or Left(exception)

359

360

// Pattern matching style processing

361

String outcome = result.fold(

362

exception -> "Failed with: " + exception.getMessage(),

363

value -> "Succeeded with: " + value

364

);

365

366

// Helper methods with checked exceptions

367

static String riskyOperation() throws IOException {

368

// Some operation that might throw

369

return "success";

370

}

371

372

static CheckedFunction1<String, Integer> parseToInt = Integer::parseInt;

373

```

374

375

### Validation - Accumulating Validation

376

377

Represents validation results that can accumulate multiple errors, useful for form validation and data processing.

378

379

```java { .api }

380

/**

381

* Validation that accumulates errors - either Valid(value) or Invalid(errors)

382

*/

383

interface Validation<E, T> extends Value<T> {

384

// Factory methods

385

static <E, T> Validation<E, T> valid(T value); // Create Valid instance

386

static <E, T> Validation<E, T> invalid(E error); // Create Invalid with single error

387

static <E, T> Validation<E, T> invalid(E... errors); // Create Invalid with multiple errors

388

static <E, T> Validation<E, T> invalid(Iterable<? extends E> errors);

389

390

// Conditional creation

391

static <E, T> Validation<E, T> fromTry(Try<? extends T> tryValue, Function<Throwable, E> errorMapper);

392

static <E, T> Validation<E, T> fromEither(Either<E, ? extends T> either);

393

static <E, T> Validation<E, T> fromOption(Option<? extends T> option, E ifNone);

394

395

// State checking

396

boolean isValid(); // true if Valid, false if Invalid

397

boolean isInvalid(); // true if Invalid, false if Valid

398

399

// Value access

400

T get(); // Get value, throws if Invalid

401

T getOrElse(T other); // Get value or return other if Invalid

402

T getOrElse(Supplier<? extends T> supplier);

403

404

// Error access

405

Seq<E> getError(); // Get errors, throws if Valid

406

407

// Transformation operations

408

<U> Validation<E, U> map(Function<? super T, ? extends U> mapper);

409

<U> Validation<U, T> mapError(Function<E, U> errorMapper);

410

<F, U> Validation<F, U> bimap(Function<E, F> errorMapper, Function<? super T, ? extends U> valueMapper);

411

<U> Validation<E, U> flatMap(Function<? super T, ? extends Validation<E, ? extends U>> mapper);

412

413

// Filtering

414

Validation<E, T> filter(Predicate<? super T> predicate, E ifFalse);

415

Validation<E, T> filter(Predicate<? super T> predicate, Supplier<? extends E> errorSupplier);

416

417

// Combining validations (accumulates errors)

418

<U> Validation<E, Tuple2<T, U>> zip(Validation<E, ? extends U> that);

419

<U, R> Validation<E, R> zipWith(Validation<E, ? extends U> that,

420

BiFunction<? super T, ? super U, ? extends R> mapper);

421

422

// Applicative operations for accumulating multiple validations

423

static <E, T1, T2, R> Validation<E, R> combine(

424

Validation<E, T1> v1, Validation<E, T2> v2,

425

BiFunction<T1, T2, R> function);

426

427

static <E, T1, T2, T3, R> Validation<E, R> combine(

428

Validation<E, T1> v1, Validation<E, T2> v2, Validation<E, T3> v3,

429

Function3<T1, T2, T3, R> function);

430

// ... up to combine8

431

432

// Folding operations

433

<U> U fold(Function<? super Seq<E>, ? extends U> invalidMapper,

434

Function<? super T, ? extends U> validMapper);

435

436

// Conversion operations

437

Either<Seq<E>, T> toEither(); // Invalid -> Left(errors), Valid -> Right(value)

438

Option<T> toOption(); // Invalid -> None, Valid -> Some(value)

439

Try<T> toTry(); // Invalid -> Failure, Valid -> Success

440

}

441

442

/**

443

* Valid variant containing the validated value

444

*/

445

class Valid<E, T> implements Validation<E, T> {

446

T get(); // Returns the valid value

447

}

448

449

/**

450

* Invalid variant containing accumulated errors

451

*/

452

class Invalid<E, T> implements Validation<E, T> {

453

Seq<E> getError(); // Returns the accumulated errors

454

}

455

```

456

457

**Usage Examples:**

458

459

```java

460

import io.vavr.control.Validation;

461

import io.vavr.collection.List;

462

import static io.vavr.control.Validation.*;

463

464

// Form validation example

465

public class Person {

466

private final String name;

467

private final String email;

468

private final int age;

469

470

public Person(String name, String email, int age) {

471

this.name = name;

472

this.email = email;

473

this.age = age;

474

}

475

}

476

477

// Individual field validations

478

static Validation<String, String> validateName(String name) {

479

return name != null && name.trim().length() >= 2

480

? valid(name.trim())

481

: invalid("Name must be at least 2 characters");

482

}

483

484

static Validation<String, String> validateEmail(String email) {

485

return email != null && email.contains("@")

486

? valid(email)

487

: invalid("Email must contain @");

488

}

489

490

static Validation<String, Integer> validateAge(Integer age) {

491

return age != null && age >= 0 && age <= 150

492

? valid(age)

493

: invalid("Age must be between 0 and 150");

494

}

495

496

// Combining validations (accumulates all errors)

497

static Validation<List<String>, Person> validatePerson(String name, String email, Integer age) {

498

return Validation.combine(

499

validateName(name).mapError(List::of),

500

validateEmail(email).mapError(List::of),

501

validateAge(age).mapError(List::of)

502

).ap((n, e, a) -> new Person(n, e, a));

503

}

504

505

// Usage

506

Validation<List<String>, Person> result = validatePerson("", "invalid-email", -5);

507

// result.isInvalid() == true

508

// result.getError() == ["Name must be at least 2 characters", "Email must contain @", "Age must be between 0 and 150"]

509

510

// Successful validation

511

Validation<List<String>, Person> success = validatePerson("John", "john@example.com", 30);

512

// success.isValid() == true

513

// success.get() == Person("John", "john@example.com", 30)

514

515

// Working with validation results

516

String message = result.fold(

517

errors -> "Validation failed: " + errors.mkString(", "),

518

person -> "Valid person: " + person

519

);

520

521

// Converting to other types

522

Option<Person> maybePerson = success.toOption();

523

Either<List<String>, Person> eitherPerson = result.toEither();

524

```