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 — to 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.
Thirteen Focused Journeys
Each journey is designed for a single sitting (20-65 minutes). Short enough to stay focused; long enough to build real understanding.
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 | Duration | Exercises | Focus |
|---|---|---|---|
| Effect API | ~65 min | 15 | Effect paths, ForPath, Contexts |
Expression Journey
| Journey | Duration | Exercises | Focus |
|---|---|---|---|
| Expression: ForState | ~25 min | 11 | Named fields, guards, pattern matching, zoom |
Concurrency Journeys
| Journey | Duration | Exercises | Focus |
|---|---|---|---|
| Concurrency: VTask | ~45 min | 16 | Virtual threads, VTask, VTaskPath, Par combinators |
| Concurrency: Scope & Resource | ~30 min | 12 | Structured concurrency, resource management |
Resilience Journey
| Journey | Duration | Exercises | Focus |
|---|---|---|---|
| Resilience Patterns | ~45 min | 22 | Circuit breaker, saga, retry, bulkhead |
Core Types Journeys (Foundation)
| Journey | Duration | Exercises | Focus |
|---|---|---|---|
| Foundations | ~40 min | 24 | Kind, Functor, Applicative, Monad |
| Error Handling | ~30 min | 20 | MonadError, Either, Maybe, Validated |
| Advanced Patterns | ~40 min | 26 | Natural Transformations, Coyoneda, Free Ap, Static Analysis |
Optics Journeys
| Journey | Duration | Exercises | Focus |
|---|---|---|---|
| Lens & Prism | ~40 min | 30 | Lens, Prism, Affine fundamentals |
| Traversals & Practice | ~40 min | 27 | Traversals, composition, real-world use |
| Fluent & Free DSL | ~35 min | 22 | Fluent API, Free Monad DSL |
| Focus DSL | ~35 min | 29 | Type-safe path navigation, container widening |
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 struggling for five minutes 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 or later: the library uses modern Java features
- 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 (4 sessions)
Core: Foundations → Error Handling → Effect API → Optics: Lens & Prism
Optics Specialist (4 sessions)
Lens & Prism → Traversals → Fluent & Free → Focus DSL
Full Curriculum (13 sessions)
All journeys in recommended order. 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
- One journey per sitting. Each journey builds internal momentum. Splitting them reduces learning.
- 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
Expression Track:
- ForState Journey - named fields, guards, pattern matching, zoom
Concurrency & Resilience Track:
- VTask Journey - virtual threads and Par combinators
- Scope & Resource Journey - structured concurrency
- Resilience Patterns Journey - circuit breaker, saga, retry, bulkhead
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
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