Expression: ForPath Parallel Composition Journey

What You'll Learn

  • How ForPath.par() combines independent computations using applicative semantics
  • Short-circuit behaviour when one computation fails (MaybePath, EitherPath)
  • True parallel execution with VTaskPath on virtual threads
  • Chaining sequential operations after parallel composition
  • The difference between applicative (par) and monadic (from) composition

Duration: ~20 minutes | Tutorials: 1 | Exercises: 9

Journey Overview

When building workflows with for-comprehensions, some computations are genuinely independent: fetching a user profile and fetching application configuration, for example, have no dependency on each other. Using .from() chains these sequentially via flatMap, even though parallelism is safe. ForPath.par() lets you express this independence directly.

ForPath.par(pathA, pathB) → Steps2 → .let() / .from() / .yield()
ForPath.par(pathA, pathB, pathC) → Steps3 → .let() / .from() / .yield()

For VTaskPath, par() spawns virtual threads via StructuredTaskScope, achieving true concurrency. For other Path types, execution is sequential but the code documents the dependency structure of your workflow.

Read First

Before starting this tutorial, read the ForPath Comprehension chapter, particularly the ForPath Parallel Composition section.


Tutorial 02: ForPath Parallel Composition (~20 minutes)

File: Tutorial02_ForPathParallel.java | Exercises: 9

Master parallel composition across multiple Path types, from simple value combination to true concurrent execution with virtual threads.

What you'll learn:

  • Basic par(2) and par(3) with MaybePath
  • Short-circuit behaviour when a computation fails
  • EitherPath error propagation with par()
  • IdPath composition with Id.of() wrapping
  • IOPath lazy composition with par()
  • VTaskPath true parallelism with timing verification
  • Chaining .let() after par()
  • Comparing par() (applicative) vs from() (monadic) semantics

Key insight: par() expresses independence, not necessarily concurrency. The same code works across all Path types, but only VTaskPath delivers true parallel execution. This separation of intent from implementation lets you write correct, clear code regardless of the underlying execution model.

Links to documentation: ForPath Comprehension

Hands On Practice


Exercise Progression

ExerciseConceptDifficulty
1Basic par(2) with MaybePathBeginner
2Short-circuit on NothingBeginner
3par(3) with three valuesBeginner
4EitherPath par(2)Intermediate
5IdPath par(3) with Id.of()Intermediate
6IOPath par(2)Intermediate
7VTaskPath true parallelismAdvanced
8Chaining .let() after par()Intermediate
9par() vs from() comparisonAdvanced

Previous: Expression: ForState Next: Resilience Patterns