Interactive Tutorials: Learn Higher-Kinded-J by Building
The best way to understand Higher-Kinded Types and Optics is not to read about them but to write them: run a test, watch it fail, change one line, and watch it pass. This chapter is built around that loop.
What Makes These Tutorials Different?
Rather than passive reading, we will:
- Write real code by replacing
answerRequired()placeholders with working implementations - Get immediate feedback because each test fails until our solution is correct
- Build progressively: earlier concepts become tools for later challenges
- See practical applications: every exercise solves a problem Java developers face routinely
Think of the chapter as a guided laboratory for functional programming patterns in Java.
Nineteen Focused Journeys
Each journey covers one topic in a handful of tutorials, and the tables give each one's exercise count. The end of a tutorial is a natural place to stop, and tutorialProgress shows where we left off.
Effect API Journey (Recommended)
After completing Core: Foundations the Effect API journey is the recommended next step. It teaches the primary user-facing API of Higher-Kinded-J.
| Journey | Exercises | Focus |
|---|---|---|
| Effect API | 17 | Effect paths, ForPath, Contexts |
Monad Transformers Journey
| Journey | Exercises | Focus |
|---|---|---|
| Monad Transformers | 29 | When Path isn't enough, async + absence, stacking, MTL |
Expression Journeys
| Journey | Exercises | Focus |
|---|---|---|
| Expression: ForState | 13 | Named fields, guards, pattern matching, zoom |
| Expression: ForPath Parallel | 9 | Applicative parallel composition for Path types |
Concurrency Journeys
| Journey | Exercises | Focus |
|---|---|---|
| Concurrency: VTask | 28 | Virtual threads, VTask, VTaskPath, Par combinators |
| Concurrency: Scope & Resource | 20 | Structured concurrency, resource management |
Context Journey
| Journey | Exercises | Focus |
|---|---|---|
| Context | 59 | ScopedValue contexts for requests, security and tracing |
Effect Handlers Journey
| Journey | Exercises | Focus |
|---|---|---|
| Effect Handlers | 19 | Effect algebras, programs as values, several interpreters |
Resilience Journey
| Journey | Exercises | Focus |
|---|---|---|
| Resilience Patterns | 24 | Circuit breaker, saga, retry, bulkhead |
Core Types Journeys (Foundation)
| Journey | Exercises | Focus |
|---|---|---|
| Foundations | 37 | Kind, Functor, Applicative, Monad |
| Error Handling | 26 | MonadError, Either, Maybe, Validated |
| Advanced Patterns | 26 | Natural Transformations, Coyoneda, Free Ap, Static Analysis |
Optics Journeys
| Journey | Exercises | Focus |
|---|---|---|
| Lens & Prism | 33 | Lens, Prism, Affine fundamentals |
| Traversals & Practice | 28 | Traversals, composition, real-world use |
| Fluent & Free DSL | 22 | Fluent API, Free Monad DSL |
| Focus DSL | 90 | Type-safe path navigation, container widening |
| Batching & Coupled Updates | 13 | Request batching, plan guardrails, coupled lenses |
| Boundary Mapping | 24 | Multi-edit, ValidatedPrism, generated record mapping, boundary edge cases |
Capstone Journey
| Journey | Exercises | Focus |
|---|---|---|
| Capstone: One Line, Six Layers Grows Up | 7 | One pipeline across effects, optics, resilience and concurrency |
How the Tutorials Work
The Exercise Pattern
Each tutorial contains multiple exercises following this pattern:
@Test
void exercise1_yourFirstChallenge() {
// 1. Context: what we are working with
Either<String, Integer> value = Either.right(42);
// 2. Task: what we need to implement
// TODO: Transform the value by doubling it
Either<String, Integer> result = answerRequired();
// 3. Verification: the test checks our solution
assertThat(result.getRight()).isEqualTo(84);
}
We replace answerRequired() with working code. The test fails with a clear error message until we get it right.
Tiered Hints
Newer exercise files use a three-tier hint structure so we can read just enough to get unstuck without seeing the answer:
// Nudge: What concept applies here?
// Strategy: Which method on Either turns A into B?
// Spoiler: value.map(n -> n * 2)
Read top-to-bottom and stop as soon as we have what we need.
The Learning Loop
- Read the exercise description and the Nudge
- Write our solution in place of
answerRequired() - Run the test (Ctrl+Shift+F10 in IntelliJ, Cmd+Shift+T in Eclipse)
- Observe the result:
- ✅ Green: correct, move on
- ❌ Red: read the error message and the Strategy hint
- Iterate until we understand the pattern, not just until the test passes
Tracking Our Progress
./gradlew :hkj-examples:tutorialProgress
This task scans the tutorial test files, counts the remaining answerRequired() calls per journey, and prints a per-journey progress bar. Useful for finding our place after a break.
Getting Unstuck
If we are struggling with an exercise:
- Read the Javadoc carefully: comments contain hints and links to relevant documentation
- Check the type signatures: what type does the method expect? what does it return?
- Look at earlier exercises: we may already have used a similar pattern
- Consult the documentation: links are provided throughout the tutorials
- Peek at the solution: solutions live in
solutions/<journey>/directories. Each@Testmethod in a solution carries a Javadoc block in the Why this is idiomatic / Alternative / Common wrong attempt format; reading that prose first is usually more useful than reading the working code on its own. See the Solutions Guide for the format and how to use it.
Resist the temptation to copy-paste. We will learn far more from a genuine attempt or two than from reading the answer immediately. The struggle is where the learning happens.
Prerequisites
Required Knowledge
- Java fundamentals: records, generics, lambdas, method references
- IDE proficiency: running tests, navigating code, using auto-completion
- Basic functional concepts: helpful but not required; we introduce them as needed
Technical Setup
- Java 25: the release the library is built on today, which preview features tie it to (Prerequisites)
- Build tool: Gradle or Maven with the Higher-Kinded-J dependencies configured
- IDE: IntelliJ IDEA, Eclipse, or VS Code with Java extensions
Verify Our Setup
The fastest way is the Tutorial00_OneLineSixLayers exercise, which doubles as the chapter's anchor:
./gradlew :hkj-examples:tutorialTest --tests "*Tutorial00_OneLineSixLayers*"
If we see a test failure with "Answer required", everything is wired up correctly and we are ready to go.
Running Tutorials
Tutorial exercises are run using a dedicated Gradle task:
# Run all tutorial exercises
./gradlew :hkj-examples:tutorialTest
# Run a specific tutorial
./gradlew :hkj-examples:tutorialTest --tests "*Tutorial01_KindBasics*"
# Run VTask concurrency tutorials
./gradlew :hkj-examples:tutorialTest --tests "*TutorialVTask*"
# See progress across journeys
./gradlew :hkj-examples:tutorialProgress
Tutorial tests are excluded from ./gradlew test because they are incomplete by design. The solution tests are included and must pass to ensure each tutorial is correctly designed.
| Command | Description |
|---|---|
./gradlew test | Runs solution tests only (must pass) |
./gradlew :hkj-examples:tutorialTest | Runs tutorial exercises (expected to fail until we complete them) |
./gradlew :hkj-examples:tutorialProgress | Prints how many answerRequired() calls remain per journey |
Recommended Learning Paths
See the full Learning Paths guide for detailed sequences. A quick overview:
Quickstart (2 sessions)
Core: Foundations → Effect API
Practical FP (5 sessions)
Core: Foundations → Error Handling → Effect API → Optics: Lens & Prism → Expression: ForState
Optics Specialist (6 sessions)
Lens & Prism → Traversals → Fluent & Free → Focus DSL → Batching & Coupled Updates → Boundary Mapping
Full Curriculum (20 sessions)
All nineteen journeys in recommended order, with the Effect API over two sessions. See Learning Paths.
What We Will Build
By the end of these tutorials, we will have hands-on experience building:
From Core Types Journeys
- A form validation system using Applicative to combine independent checks
- A data processing pipeline using Monad to chain dependent operations
- An error handling workflow using
EitherandValidatedfor robust failure management - A configuration system using
Readerfor dependency injection
From Optics Journeys
- A user profile editor with deep nested updates using Lens composition
- An e-commerce order processor using Traversals for bulk operations
- A data validation pipeline combining Lens, Prism, and Traversal
- A multi-step workflow builder using the Free Monad DSL with logging and validation
Tips for Success
- Stop at the end of a tutorial. Each tutorial builds on its own earlier exercises, so its end is the natural place to pause.
- Read hints in order. Nudge first, then Strategy, then Spoiler. Stop the moment we have enough.
- Run tests frequently. Get one green before moving on; don't write all the exercises in one go.
- Experiment fearlessly. Tests provide a safety net; we cannot break anything.
- Don't rush. Understanding matters more than speed. Take breaks between journeys.
- Ask questions. Use GitHub Discussions if a concept is unclear.
Beyond the Tutorials
After completing the tutorials, continue with:
- Example Code - production-quality examples in
hkj-examples, including the order, market, payment, and draughts domains - API Documentation - deep dives into every optic and typeclass
- Complete Walkthroughs - how the patterns combine in real applications
- One Line, Six Layers - the chapter-wide anchor that ties everything in this book to a single expression
- Our own projects - apply these patterns to a real codebase
Ready to Begin?
Choose a starting point:
Recommended Path:
- Tutorial00: One Line, Six Layers (anchor + setup check)
- Foundations Journey - core concepts
- Effect API Journey - the primary user-facing API
Core Types Track (Foundation):
- Foundations Journey - HKT basics
- Error Handling Journey - error handling
- Advanced Journey - advanced patterns
Monad Transformers Track:
- Monad Transformers Journey - when the Path API isn't enough
Expression Track:
- ForState Journey - named fields, guards, pattern matching, zoom
- ForPath Parallel Journey - applicative parallel composition
Concurrency & Resilience Track:
- VTask Journey - virtual threads and Par combinators
- Scope & Resource Journey - structured concurrency
- Resilience Patterns Journey - circuit breaker, saga, retry, bulkhead
Context Track:
- Context Journey - request, security and trace contexts as values
Effect Handlers Track:
- Effect Handlers Journey - effect algebras and their interpreters
Optics Track:
- Lens & Prism Journey - start here for optics
- Traversals Journey - collections and composition
- Fluent & Free Journey - advanced APIs
- Focus DSL Journey - type-safe paths
- Batching & Coupled Updates Journey - request batching and coupled lenses
- Boundary Mapping Journey - the generated DTO boundary
Capstone:
- Capstone: One Line, Six Layers Grows Up - one pipeline across every layer
Or see Learning Paths for detailed sequences.
Remember: the goal isn't to memorise every detail. It's to develop an intuition for when and how to apply these patterns. That only comes through practice.
Previous: Introduction Next: Core Types: Foundations Journey