Release History
This page documents the evolution of Higher-Kinded-J from its initial release through to the current version. Each release builds on the foundations established by earlier versions, progressively adding type classes, monads, optics, and the Effect Path API.
- Detailed release notes for recent versions (0.3.0–0.4.5) with links to documentation
- Summary release notes for earlier versions (pre-0.3.0)
- Links to GitHub release pages for full changelogs
Recent Releases
v0.4.6-SNAPSHOT (unreleased)
Optic-Driven Request Batching
This release adds the user-facing surface around the org.higherkindedj.optics.fetch substrate so an optic traversal of N foci collapses to one batched backend call by swapping the strategy passed to Optic.modifyF. The optic core is untouched; the package is now exported and documented, the heterogeneous Id -> Entity case has a dedicated helper, and run-time failures land on the value channel as Either rather than as exceptions.
- Optic-Driven Batching: New chapter under Optics / Integration and Recipes, with three diagrams (N+1 vs batched, the optic + applicative + runner pipeline, the applicative-versus-
flatMapround cost) and a language-agnostic primer link for the DataLoader/Haxl idea.org.higherkindedj.optics.fetchis now exported from the core module;Done/Blocked/PendingKeysremain package-private so consumers interact withFetchonly through its static factories and runners SafeFetch: Total runner that captures resolver exceptions, missing-key reports, loader failures, and deadlines asEither.leftvalues on the value channel instead of thrown exceptions;SafeFetch.runCached,runAsync, andrunAsyncWithTimeoutnever throw and the safe-async future never completes exceptionally.SafeFetch.partitionsplits a per-keyEither<E, V>result list into aligned successes and failures so a partial-success batch is preserved end-to-endSourceRouter.routed: Composes per-sourceBatchLoaders with a classifier into one loader the substrate can call; one round fans out to one concurrent dispatch per source, so a list mixing user ids and product skus produces exactly one call per backend, not one call per keyBatchLoaders.chunked(loader, maxSize): Caps a single dispatch's size for backends that enforce a per-request limit ($inclause cap, HTTP query-string ceiling, GraphQL batch limit); the substrate still sees one round and the loader splits the keyset behind the curtainFetchOptics.fetchEach(source, rebuild): The type-changing list-traversal the codegen does not produce (codegen optics are type-preserving, so aTraversal<Team, UserId>cannot directly describe loading eachUserIdinto aUser); builds anOptic<S, T, A, B>from a list-reader and a rebuild function so heterogeneous fetch composes with the rest of the optic graph- Tutorial 21: New tutorial journey (exercise + teaching-solution) covering the four pieces (same-type batching, heterogeneous fetch, multi-source routing, railway errors) with five exercises and tiered hints; the solution carries the Why this is idiomatic / Alternative / Common wrong attempt commentary per exercise
- Architecture-rule update: The
optics.fetchpackage is exempted from the "no specific HKT type dependencies" rule alongside the existingoptics.util,optics.extensions, andoptics.fluentexemptions, on the same basis:SafeFetch's railway runner is built aroundEitherby design
Plan Introspection and Guardrails for Optic Batching
The audit and safety-rail layer on top of Optic-Driven Batching: a way to fold a Fetch program into a structural plan without I/O, and a per-round guard that interposes between the program and its resolver to refuse runaway batches before they leave the JVM. Both compose with SafeFetch so refusal is a value, not a thrown exception.
- Plan Introspection and Guardrails: New chapter under Optics / Integration and Recipes covering the offline
Plans.preflightwalk, the per-roundGuardfamily, and the railway-safe refusal pattern. Plans.preflight: Folds aFetchprogram into aPlan<K>with zero I/O. Each round's keyset is recorded in dispatch order; round 1 is universally observable, and later rounds are walked on stub values when the program's combine logic toleratesnull(aPlan.truncated()flag is the honest signal otherwise).Guards.maxKeysPerRound/maxRounds/maxBackendCalls/audit/none: Standard guards that pass or refuse a round at the runner boundary; compose withGuard::and. A refusal aborts the run withGuardViolationExceptioncarrying the offendingroundIndexandpendingKeys.Guards.runCached/runAsync: Drop-in replacements for the substrate runners with the guard interposed; the resolver is never called for a refused round.SafeFetch.runCachedWithGuard/runAsyncWithGuard: Railway variants that capture a refusal asEither.left(GuardViolationException); the run never throws and the safe-async future never completes exceptionally.- Tutorial 22 (exercise + teaching solution) covering the five pieces (preflight, truncation, refusal, audit, railway capture).
Test-suite consolidation (internal)
Mostly an internal refactor of the hkj-core test suite — net −822 lines while preserving 100% JaCoCo coverage. The one user-visible piece is in hkj-test: new reusable law helpers (FunctorLaws, ApplicativeLaws, MonadLaws, SelectiveLaws) and a KindEquivalence.byEqualsAfter helper that downstream users can call to verify their own type-class instances. The Kind-accepting overloads on EitherAssert / MaybeAssert / TryAssert / IOAssert / LazyAssert / ReaderAssert / ValidatedAssert / WriterAssert / VStreamAssert / VTaskAssert now match the auto-narrowing pattern of ListAssert / OptionalKindAssert / StreamAssert / IdAssert.
N-ary Coupled Lenses
The arity ladder above Lens.paired: a record with three or more cross-field invariants can now be updated atomically through a single coupled3..coupled9 call instead of nested paired workarounds.
- Coupled Fields chapter: "Three or More Coupled Fields" section rewritten to show the new ladder; the old "nest pairs / feature request" guidance is replaced.
CoupledLenses.coupled3...coupled9(inorg.higherkindedj.optics.util): seven static factories, each with two overloads mirroringLens.pairedexactly (preserving form taking(S, A, B, ...) -> S; simple form taking the constructor reference(A, B, ...) -> S). ReturnsLens<S, TupleN<...>>reconstructed atomically.hkj-processoraddsCoupledLensGenerator, wired into the existing@GenerateForComprehensionstrigger alongside the Tuple/For-step generators. Generation caps at arity 9 (cross-field invariants past that point are vanishing in practice); raising the cap is a one-line change to the generator.- Tutorial 23 (exercise + teaching solution) demonstrating
coupled3on a 3-field monotonic invariant andcoupled5on the same shape at higher arity, including the canonical "chained set throws" failure mode that coupled lenses sidestep.
v0.4.5 (22 May 2026)
A Uniform Instances Facade for Type-Class Lookup
This release introduces Instances, a single static entry point for obtaining any built-in type-class instance, replacing the three inconsistent legacy idioms (a static INSTANCE field, a generic instance() method, or an argument-taking constructor) with one predictable shape discovered by capability through IDE autocomplete. The whole codebase — tests, runnable examples, and the book — is migrated to the one idiom.
- Obtaining Instances: New
org.higherkindedj.hkt.instancespackage with theInstancesfacade and theWitnessestyped-token helper.Instances.monad/applicative/functor(token)are total (every canonical instance is at least aMonad); a single token yields all three by Java subtyping. Phantom-typed witnesses (Either,Reader,Context,State) still infer their type parameter from the assignment target, matchingEitherMonad.<L>instance()behaviour. The facade is a thin static re-export of the existing accessors — not Spring-wired, notPathRegistry/ServiceLoader-backed — so compile-time safety is preserved and no built-in instance can be missing at runtime (#522) - Partial capability lookups:
Instances.monadError,monadZeroandalternativefor canonical instances that implement the richer capability (e.g.Maybe,Optional,Try,Either,List,Stream). The error typeEofmonadErroris inferred from the assignment target; asking for a capability the instance does not have fails fast with aClassCastException, exactly as calling a non-existent method would - Argument-carrying re-exports:
Instances.validated(Semigroup),writer(Monoid),eitherT(outer),maybeT(outer),optionalT(outer),readerT(outer),stateT(outer)andwriterT(outer, Monoid). The structurally-required dependency is now a compiler-enforced, self-documenting method parameter instead of something discovered by reading a constructor - One-idiom migration: The
Instancesfacade is adopted across ~196 test files, 66 runnable examples, and 71 book pages so the documentation and examples teach a single way to obtain an instance. TheMonadReader/MonadStateMTL capability classes andTraverse/Selective/Foldableremain a separate surface, intentionally out of scope for this facade and tracked separately - Reference material: New glossary entry, a Type-Class Instances section in the cheat sheet, and a
InstancesFacadeExamplerunnable example - Bifunctor law verification: The reusable Bifunctor law harness (
LawTestPattern/TypeClassTestPattern) now verifies the first-map (first(f, fab) == bimap(f, id, fab)) and second-map (second(g, fab) == bimap(id, g, fab)) consistency laws alongside the existing identity and composition laws, so every canonical instance (Either,Tuple,Const,Validated,Writer) is checked against all four laws; explicit named consistency tests added forEither(Left/Right) andTuple(#461) - Collection-path fold family:
ListPathandStreamPathgain the monoid-stylefold(identity, op)and theFoldable-stylefoldMap(Monoid, fn), plusfoldRightonStreamPath, matching the existingVStreamPath/VStreamContextfold surface so the same reduction reads identically across every sequence-like path and stays inside the path chain. Documented in the cheat sheet and the Foldable chapter, withCollectionPathsExampleupdated to fold without unwrapping (#462) - Effect Path
toString()standardisation: A sharedPathToStringhelper gives every Effect Path type one debugging-friendly, greppabletoString()convention: the round-parenthesis wrapper formTypeName(inner), a uniform angle-bracketed sentinel vocabulary (<deferred>,<stream>,<empty>,<pending>,<failed>), and bounded rendering for collection-backed paths (ListPath,NonDetPath,WriterPathlogs) with an explicit…(+k more)marker so a large backing collection never produces an unbounded log line.IdPathis now null-safe andLazyPathnever forces its computation when rendered; all changed path classes hold at 100% line/branch coverage (#530)
Expanded hkj-checker Compile-Time Diagnostics
This release grows the hkj-checker javac plugin from a single Path-type-mismatch check into a catalogue of twelve compile-time checks, adds per-check severity configuration, and consolidates the relevant OpenRewrite recipes into compile-time feedback. Several further candidate checks were investigated and deliberately not shipped — kept as passing characterization tests that document why — because the targeted error is unreachable on modern javac, already caught by the compiler, or only detectable via a rot-prone heuristic; the strict no-false-positives policy is preserved throughout.
- Compile-Time Checks: Eleven new checks join
path-type-mismatch:effect-composition,transformer-missing-monad,free-switch-exhaustive,discarded-effect,state-t-mapt-arity,error-type-mismatch,kind-value-narrow,witness-arity,via-non-path,map-nests-effect, andmigration-nudge. Each is a companion to a real javac error or the sole signal for an otherwise-silent mistake (a discarded lazy effect, a silently-erased error type, a nested effect); the sole-signal heuristics default to a warning - Per-check severity: The plugin-argument grammar adds
severity:<id>=error|warnalongside the globalseverity=anddisable=<id>, so the warn-default checks can be promoted per project. Unknown ids and unparseable values are ignored so a typo never breaks the build - Recipe consolidation:
migration-nudgefolds theConvertRawFreeToFreePathandDetectInjectBoilerplateOpenRewrite diagnoses into advisory compile-time nudges;free-switch-exhaustiveandwitness-aritydo the same for the Free-switch andWitnessArityrecipes - Documentation:
tooling/compile_checks.mdis now the authoritative checker catalogue (every check, its default severity, and the configuration grammar); the effect/transformers/optics Common Compiler Errors chapters were corrected where they described errors modern javac no longer emits and cross-linked to the catalogue
Hardened hkj-openrewrite Recipes
This release audits and hardens the hkj-openrewrite migration recipes — correctness fixes, broader detection, type-safe matching, new 0.5.0 deprecation recipes, and a near-quadrupled test suite (9 → 34 tests).
- Arity bounds:
AddArityBoundsToTypeParametersnow emitsTypeArity.BinaryforKind2,BifunctorandProfunctor(previously alwaysUnary, which generated incorrect bounds), detects witness use across fields, local variables, the class hierarchy, nested generics and wildcard bounds (not just method signatures), and no longer emits malformed output (<Fextends …>); the existing-bound intersection case is also fixed - Type-safe detection:
ConvertRawFreeToFreePathandDetectInjectBoilerplateuse a type-attributedMethodMatcherinstead of rendered-string matching (a user type namedFree, fully-qualified calls, or static imports no longer mis-fire or get missed);AddHandleErrorCasenow also handles switch expressions with whole-word case matching; the three detect-only recipes emit OpenRewrite search-result markers instead of rewriting source with TODO comments - 0.5.0 deprecation migration: New
MigrateDeprecationsTo0_5_0recipe group renamesStateTKind.narrowK→narrowandKindValidator.narrowWithPattern→narrowHolder
Library and Build Refinements
This release also marks one wildcard-witness escape hatch for removal, makes the Java 25 toolchain self-provisioning, and lands the module-internal foundation for batched optic data access.
StateTKind.narrowKdeprecation:StateTKind.narrowKaccepts a wildcard-witnessKind<?, A>, bypassing the HKT witness type safety enforced everywhere else in the library; it has no callers and the type-safenarrow(Kind)already covers the use case. It is now@Deprecated(forRemoval = true)for removal in 0.5.0, with theMigrateDeprecationsTo0_5_0OpenRewrite recipe automating thenarrowK→narrowrename (#455)- Java 25 toolchain auto-provisioning:
settings.gradle.ktsapplies thefoojay-resolver-conventionplugin so Gradle downloads and provisions a matching Java 25 JDK automatically when the build machine does not already have one, removing a manual setup step for new contributors - Request-batching substrate: New module-internal
org.higherkindedj.optics.fetchpackage: a free-applicative-styleFetch<K, V, A>(Done/Blocked) andFetchApplicativethat plug into the opticmodifyFseam so a traversal whose focused values are loaded from a backend coalesces those N loads into one batched call (the classic N+1), with a transport- and datastore-neutralBatchLoadercontract and round-basedrunCached/runAsyncrunners carrying a per-run request cache. The package is intentionally not exported — it is the foundation for later data-access capabilities and carries no public API yet (#539)
v0.4.4 (16 May 2026)
The hkj-test Module, PCollections Integration, and Type Class Enrichments
This release ships hkj-test, a new publishable module providing fluent AssertJ assertion helpers for every public Higher-Kinded-J type, validates and extends PCollections persistent-collection support across the HKT and optics infrastructure, enriches the type class hierarchy with Alternative.orElseAll(Iterable) and MonadZero.filter, makes ForState.zoom and ReaderPath.magnify optic-polymorphic, standardises the internal validation package, and refreshes the Tooling chapter to lead with the recommended build-plugin setup.
- hkj-test Module: New publishable module (
io.github.higher-kinded-j:hkj-test) with 19 user-facing assertion classes covering the discriminated unions (Either,Maybe,Try,Validated,Lazy), the Reader/Writer/State trio, the effect types (IO,VTask,VStream), every monad transformer, and theFree/EitherFalgebras. Published as a JPMS module (org.higherkindedj.test) so a single dependency declaration suffices; Java 25 with--enable-previewcanimport module org.higherkindedj.test;to bring every helper into scope. Backed by anAssertContract<S, A>contract-test framework holding the module at a 100% line+instruction coverage gate, plus a new/hkj-testClaude Code skill - hkj-test Coverage Extension: Seven further assertion classes promoted from
hkj-coretest sources into the published artifact: theList/OptionalKind/Stream/IdKind-narrowing wrappers (assertThatList,assertThatOptionalKind,assertThatStream,assertThatId) and theVTaskPath/VStreamPath/VTaskContextpath-and-context assertions - PCollections HKT Compatibility: Validates that PCollections persistent collections (
PVector,PStack) work through the existingListKind/ListMonad/ListTraverse/ListSelective/Alternativeinfrastructure viajava.util.Listcompatibility with no production code changes, backed by integration tests, jQwik property tests for the Functor/Monad/Foldable laws, JMH benchmarks, and a runnable example - PCollections Optics Generators: Seven
TraversableGeneratorplugins teaching@GenerateTraversalsand@GenerateFocusto navigate PCollections types (PVector,PStack,PSet,PSortedSet,PBag,PMapvalues,PSortedMapvalues); auto-discovered whenorg.pcollectionsis on the annotation-processor classpath. The generator ecosystem grows from 23 to 30 implementations - Traversals.forMapValuesCollecting: Map-shaped companion to
forIterableCollecting, with a bounded single-arg overload forjava.util.Mapsubtypes (PCollectionsPMap/PSortedMap, GuavaImmutableMap) and an unbounded two-arg overload for non-java.util.Maptypes (Eclipse Collections, Vavr);EachInstances.mapValuesEachCollectingmirrors both for the Focus DSL - Alternative.orElseAll(Iterable): Dynamically-sized counterpart to the existing varargs
orElseAlland analogue of Haskell'sasum/msum, folding an iterable of alternatives viaorElse.ListMonadandStreamMonadoverride it to avoid O(n^2) result copying and deeply-nestedStream.concatchains while preserving lazy evaluation - MonadZero.filter: New default
filter(Predicate, Kind)derived fromflatMap+of/zero, with allocation-freeListMonad/StreamMonadoverrides; the duplicated guard pattern is refactored out ofFor.when,ForState.when/zoom, and theForPathcomprehension builders to callfilterdirectly - Axes of Transformer Transformation:
ForState.zoomnow acceptsFocusPath,AffinePath(short-circuiting viaMonadZero.zero()when the focus is absent), andIsoin addition toLens;ReaderPathgains optic-awaremagnify(Getter)andmagnify(FocusPath)overloads alongside the existinglocal(Function)escape hatch. New chapter plus aMagnifyServiceLayerExampleand Tutorial 05 (Optic-Polymorphic Zoom and Magnify) - Validation package standardised: the
Operationenum gainsWIDEN/NARROW/OR_ELSE_ALL/FILTER,ValidationexposesKIND/FUNCTION/TRANSFORMER/COREstatic fields,FunctionValidatorgainsvalidateMap(44 Functor/Monad sites migrated), andKindValidator.narrowWithPatternis@Deprecated(forRemoval=true)for removal in 0.5.0 in favour of the newnarrowHolder
Documentation & Tutorial Improvements
- Build Plugins as the Documented Default: The Tooling chapter is reordered so Build Plugins leads as the recommended path and Manual Setup follows as the explicit fallback, with Previous/Next navigation rewired across the chapter to keep the sequence linear. The Spring Boot Quickstart gains an
hkj-bomoption (Gradle and Maven forms) so all HKJ module versions are declared once - Where to Start: New task-first landing page that asks "what are you trying to do?" before routing to the chapter-level decision trees, with five top-level branches (failure/absence, nested data, async/IO, sequencing, polymorphic code) plus a Combining Tools section covering the most common cross-axis combinations
v0.4.3 (7 May 2026)
Pluggable HTTP Error Status Strategy, Header Carriers, and Documentation Refresh
This release introduces pluggable error-to-status mapping for hkj-spring, lets domain errors inject custom HTTP headers (Retry-After, WWW-Authenticate, Location, ...), and delivers a comprehensive refresh of the hkj-book: the Effect Path API chapter restructured into five sub-chapters, optics documentation reorganised along Diátaxis lines, the Monad Transformers chapter rebuilt as a coherent learning path with a hands-on tutorial track, the Foundations chapter rewritten around a single recurring "one line, six layers" anchor, and refreshed hands-on materials with tiered hints and per-exercise teaching prose across every tutorial journey.
- HttpHeaderCarrier: Mix-in interface for error values to inject custom HTTP headers into the response. All Effect Path return-value handlers now apply carrier headers before writing the JSON body, enabling
429 Too Many Requestserrors to surfaceRetry-After,401 Unauthorizederrors to surfaceWWW-Authenticate, and201 Created/301 Moved Permanentlyoutcomes to surfaceLocation - ErrorStatusCodeStrategy: Pluggable strategy bean replacing the hard-coded heuristics in
ErrorStatusCodeMapper. The defaultDefaultErrorStatusCodeStrategycombines explicit mappings fromhkj.web.error-status-mappings(by simple or fully-qualified class name) with token-aware heuristics on the simple class name and the configured default status code; teams can supply a customErrorStatusCodeStrategybean to override end-to-end - hkj.web.error-status-mappings: New configuration property for explicit error-class to HTTP-status mappings, supporting both simple and fully-qualified class names. Covers 4xx/5xx codes outside the heuristic table such as
409 Conflict,422 Unprocessable Entity,429 Too Many Requests, and503 Service Unavailable - Tokenized class-name matching:
ErrorStatusCodeMappernow splits class names on CamelCase boundaries and matches whole tokens, eliminating false positives likeRevalidationErrorpreviously matching thevalidationheuristic
Documentation @ Tutorial Improvements
- Effect Path API Restructure: The Effect Path API chapter is reorganised into five sub-chapters (Quickstart, Core Paths, Optics Integration, Advanced Paths, Reference) so a Java developer reaches runnable Effect Path code in under five minutes without advanced material blocking the beginner path. New API-level Effect Path quickstart with three runnable examples covering
MaybePath,EitherPath, andForPath - Manual Gradle and Maven Setup: Book-level Quickstart trimmed to lead with the recommended
hkj-gradle-pluginandhkj-maven-pluginsetup; full manual build-file configuration extracted to a new dedicated page so adopters who must wire dependencies by hand have one canonical reference - Optics Documentation Reorganised: Optics chapter restructured along Diátaxis lines: narrative pages focus on learning, while new dedicated reference pages serve returning readers. New Quickstart, Annotations at a Glance, Optic Capabilities, Conversions, Decision Trees, Compiler Errors, and Production Readiness;
- Monad Transformers Learning Path: Transformers chapter rebuilt as a coherent learning path: new Quickstart, Transformers at a Glance, Migration Cookbook, When to Drop to Transformers, Common Errors, and Transformer Capstone.
- Monad Transformers Hands-On Track: New tutorial journey in
hkj-examples: Tutorial 01 (When Path Isn't Enough, EitherT entry), Tutorial 02 (Async with Absence, OptionalT/MaybeT), Tutorial 03 (Stacking Transformers), and Tutorial 04 (Polymorphic Capabilities). Default test task runs solutions; newtutorialTesttask includes the in-progress exercises with predictable failures - Foundations Chapter Refresh: Foundations reframed as the engine-room tour readers reach after shipping with the Effect Path API, Optics, or Monad Transformers, with three reading paths (mechanism tour, generic-code author, library extender) anchored on a single recurring "one line, six layers" service-method example. New pages: One Line, Six Layers, Lifting the Hood (end-to-end trace through
widen/ dispatch /narrowwith allocation costs), and Foundations FAQ (ten direct answers including comparisons with Vavr, Cyclops, Arrow-Kt, and the Valhalla question). - Hands-On Tutorial Refresh: Refreshed every tutorial journey: Tutorial 00 chapter anchor (One Line, Six Layers, setup-check exercise), new Capstone Journey building the chapter anchor up to a real workflow, tiered hint structure (Nudge / Strategy / Spoiler) on tutorial files, and hand-rolled per-exercise teaching prose on every
@Testin every solution file in the Why this is idiomatic / Alternative / Common wrong attempt format. NewtutorialProgressGradle task countsanswerRequired()placeholders across journeys and prints a per-journey progress bar
v0.4.2 (18 April 2026)
EffectBoundary, Claude Code Skills, and Spring HTTP Ergonomics
This release introduces EffectBoundary for gradual Spring adoption of Free-monad programs, delivers a complete hkj-spring order-processing showcase demonstrating the boundary pattern end-to-end, ships a suite of six Claude Code skills providing in-editor guidance to HKJ adopters, extends the Effect Path return-value handlers with @ResponseStatus honouring and a canonical @WebMvcTest slice-test recipe, widens the Effectful capability interface for cross-path error recovery, and adds EitherPath.bimap and Try.attempt(CheckedSupplier) alongside targeted bug fixes.
- EffectBoundary: Gradual adoption boundary bridging
Freeprograms into the Effect Path handler ecosystem via IO-target (production) and Id-target (test) interpreters. Spring integration adds@EnableEffectBoundary,@Interpretercomponent meta-annotation,@EffectTestslice,FreePathReturnValueHandler, andObservableEffectBoundary(Micrometer), letting teams adopt effects module-by-module without rewriting existing code - Effect Boundary Showcase: Complete Spring Boot order-processing example demonstrating the full boundary pattern: three effect algebras (
OrderOp,InventoryOp,NotifyOp) composed into programs, interpreters discovered as Spring beans via@Interpreter,OrderServicebuilding pureFree<F, A>programs,OrderControllerinvokingboundary.runIO()with the existingIOPathReturnValueHandler,TestBoundary+Idpure tests running in milliseconds, full MockMvc integration tests, andObservableEffectBoundarymetrics exposed via actuator - Claude Code Skills Suite: Six Claude Code skills (
/hkj-guide,/hkj-optics,/hkj-effects,/hkj-bridge,/hkj-spring,/hkj-arch) providing contextual guidance on Path selection, optics generation, Free monads and effect algebras, effects-optics bridging, Spring adoption ladder, and functional-core architecture; auto-triggered on keywords or invoked directly - @ResponseStatus Support: All nine Effect Path return-value handlers (
EitherPath,MaybePath,TryPath,ValidationPath,IOPath,CompletableFuturePath,VTaskPath,FreePath,VStreamPath) now honour@ResponseStatuson handler methods via the newSuccessStatusResolver, with controller-class fallback and meta-annotation support; POSTs can return canonical201, DELETEs can return204with body suppressed - @WebMvcTest Slice Recipe: Canonical slice-test pattern using
@ImportAutoConfiguration({HkjAutoConfiguration, HkjJacksonAutoConfiguration, HkjWebMvcAutoConfiguration})with@MockitoBean, coveringRight→200and tagged-errorLeft→404 - Effectful Capability Widening:
handleError,handleErrorWith, andguaranteenow live on the sealedEffectfulinterface;handleErrorWithacceptsFunction<? super Throwable, ? extends Effectful<A>>soIOPathandVTaskPathcan cross-recover while preserving the receiver's concrete type - EitherPath.bimap: Transform error and success values in a single call; equivalent to
.mapError(errorFn).map(successFn)with laziness on the unused branch - Try.attempt: New
Try.attempt(CheckedSupplier)entry point for Java APIs that throw checked exceptions (Files.readString,Class.forName, JDBC, reflection).CheckedSupplier<T, X extends Exception>inhkj-apideclaresthrows Xonget(), avoiding the lambda target-type ambiguity ofTry.of(Supplier) hkj-checkerregistered ontestAnnotationProcessorand every source-set annotation-processor classpath via the Gradle plugin; the Maven plugin defensively appends HKJ entries to user-suppliedtestAnnotationProcessorPaths, resolvingerror: plug-in not found: HKJCheckerduring test compilationhkj.web.either.default-error-statusproperty now binds and takes effect (#490); legacy flat pathhkj.web.default-error-statuspreserved as a backward-compatible alias, with end-to-end@WebMvcTestregression coverage- Test coverage uplift across
FocusProcessor,FoldProcessor,ForComprehensionProcessor, the optics processors,EffectAlgebra/ComposeEffects/Path processors, andKindFieldAnalyser, plus a new@ExcludeFromJacocoGeneratedReportutility
v0.4.1 (8 April 2026)
Effect Handlers, Spring Observability, and Monad Transformer Enhancements
This release introduces algebraic effect handlers with annotation-driven code generation, delivers a complete payment processing example with four interpretation modes, adds FreePath for-comprehension support, extends Spring Boot integration with VTask/VStream metrics and virtual thread health monitoring, adds mapT to all monad transformers, and includes significant bug fixes for stack safety, traverse performance, and resilience patterns.
@EffectAlgebra- Annotation processor generating five classes per sealed interface: Kind marker + Witness, KindHelper, Functor (auto-detectsmapKfor CPS vs cast-through), Ops (smart constructors +Boundinner class), and abstract interpreter skeleton with exhaustiveswitchdispatch@ComposeEffects- Annotation processor generating composition infrastructure for 2-4 effect algebras:Injectfactory methods via right-nestedEitherF, composedFunctor,BoundSetrecord, andinterpret()bridge method@Handles- Compile-time validation that interpreter classes handle all operations in an effect algebra; reports missing handlers as errors and extra handlers as warnings- EitherF - Sum type for composing effect algebras via right-nesting, with
Injectfor embedding operations,Free.translatefor program transformation, andInterpreters.combine()for 2-4 effect dispatch - HandleError:
Free.HandleErrorwraps sub-programs with typed error recovery; delegates toMonadError.handleErrorWithwhen available, silently ignored otherwise. Supports subclass matching viaClass<E>token - ErrorOp - Effect algebra for typed error raising within Free programs, with
ErrorOps.raise()smart constructor andBound<E, G>for composed effects - StateOp - Optics-native state effect algebra with 6 operations (
View,Over,Assign,Preview,TraverseOver,GetState), CPS for correct functor mapping, andStateOpInterpreter/IOStateOpInterpreterinterpreters - ProgramAnalyser - Static analysis of Free program trees: counts instructions (
Suspend), recovery points (HandleError), parallel scopes (Ap), and opaque regions (FlatMapped). All counts are lower bounds. - Payment Processing - Complete worked example with 4 effect algebras, 13 interpreters across production (
IO), testing (Id), quote (fee estimation), and audit (WriterT) modes; 12 tests and 6 tutorials - Effect Handlers Introduction - Motivational documentation covering the DI gap, programs-as-data, DOP connection, terminology bridge mapping FP concepts to Java equivalents, and when-to-use guidance
- FreePath For-Comprehensions - FreePath as the 10th path type in the
ForPathsystem, withfrom(),let(),focus(),par(),traverse(),sequence(),flatTraverse(), andyield()steps - FreePath.attempt() - Captures outcome as
Either<Throwable, A>, mapping success toRightand handling errors asLeft - mapT - New method on all 6 monad transformers (
EitherT,MaybeT,OptionalT,WriterT,ReaderT,StateT) for transforming the outer monad layer without unwrapping. Custom AssertJ assertions added forWriterT,ReaderT, andStateT - VTask/VStream Metrics -
HkjMetricsServicerecords success/error counts and execution duration forVTaskPathReturnValueHandlerand element counts forVStreamPathReturnValueHandler; metrics exposed via/actuator/hkjendpoint - Virtual Thread Health Indicator - Spring Boot health indicator monitoring virtual thread availability with configurable threshold
- OpenRewrite Recipes -
AddHandleErrorCaseRecipefor missingHandleError/Apswitch cases,ConvertRawFreeToFreePathRecipeforFreePathmigration,DetectInjectBoilerplateRecipefor@ComposeEffectsadoption - FList - Lightweight immutable cons-list replacing O(n^2)
LinkedListcopy inListTraverse,StreamTraverse, andVStreamTraversewith O(n) cons accumulation - Free.foldMap stack safety: added trampolining to prevent
StackOverflowErroron deep program chains - FreeAp.foldMap stack safety: added trampolining for deep applicative trees
- CircuitBreaker: reset failure count on success in
HALF_OPENstate - ConstBifunctor: fix NPE in
second()by applying function to second element - IO.raceIO: fix
ClassCastExceptioninfirstVTaskSuccessfor checked exceptions - Lazy: add reentrant-call detection to prevent infinite recursion
- Bulkhead: add permit-release guard to prevent negative permits
- VStreamPar.merge: join background producer thread on close to prevent thread leak
- VStreamThrottle: replace dual
AtomicLongwithAtomicReference<WindowState>CAS loop - Free
Fparameter tightened fromWitnessArity<?>toWitnessArity<TypeArity.Unary>across the entire hierarchy, eliminating raw type usage - Additional edge case tests for
NavigatorClassGenerator,FocusProcessor, andForPathStepGenerator - JMH Benchmarks: 7 new benchmarks for EitherF dispatch, Free.translate, HandleError overhead, ProgramAnalyser traversal, and program construction cost
v0.4.0 (22 March 2026)
SPI-Aware Path Widening, Expanded Plugin Ecosystem, and Focus DSL Restructure
This release introduces SPI-aware path widening for the Focus DSL, allowing automatic AffinePath and TraversalPath generation based on container cardinality, expands the TraversableGenerator plugin ecosystem to 23 generators across 6 library families, adds Traversal.asFold() for read-only monoidal aggregation, restructures the Focus DSL documentation into dedicated pages, and delivers comprehensive test coverage and Javadoc quality improvements across processor modules.
- SPI-Aware Path Widening: Automatic path type inference based on container cardinality:
ZERO_OR_ONEproducesAffinePath,ZERO_OR_MOREproducesTraversalPath, eliminating manual.each()and.some()calls in generated navigators - Cardinality-Based Widening:
TraversableGeneratorSPI extended withCardinalityenum, priority system (PRIORITY_FALLBACK,PRIORITY_DEFAULT,PRIORITY_OVERRIDE),widenCollectionsopt-in attribute, and wildcard type resolution for? extends T,? super T, and bare? - Nested Container Widening: Compound types like
Optional<List<String>>resolve correctly through recursive cardinality analysis, with navigator field collision detection - Generator Plugin Ecosystem: 23
TraversableGeneratorimplementations across 6 library families: base JDK (Array, List, Set, Optional, MapValue), Apache Commons Collections4 (HashBag, UnmodifiableList), Eclipse Collections (ImmutableBag, MutableBag, ImmutableList, MutableList, ImmutableSet, MutableSet, ImmutableSortedSet, MutableSortedSet), Google Guava (ImmutableList, ImmutableSet), Vavr (List, Set), and HKJ native (Either, Maybe, Try, Validated) - Traversal.asFold(): Conversion from any
Traversalto a read-onlyFoldfor monoidal aggregation, existence checks, and length counting via newConstForFoldapplicative functor - AffinePath: New
AffinePath<S, A>for zero-or-one navigation in Focus DSL, withAffineoptic interface supportinggetOrModifyandset - Portfolio Risk Analysis: Capstone example demonstrating container navigation, SPI widening, and nested optics composition
- Focus DSL documentation restructured into dedicated pages: Containers, Navigation, Effects, and Reference
- Tutorial 19: Navigator Generation: 7 exercises on annotation-driven navigator code generation
- Tutorial 20: Container Navigation: 4 exercises on SPI-aware container type navigation
- Automated SPI service declarations via Avaje SPI processor for plugin discovery
v0.3.7 (15 March 2026)
WriterT Transformer, For-Comprehension Power-Ups, Build Tooling, and Spring Virtual Thread Support
This release introduces the WriterT monad transformer with MTL-style capability interfaces, enriches for-comprehensions with parallel composition, traversal operations, and optics integration, adds compile-time Path type checking via the new hkj-checker javac plugin, delivers one-line project setup through build tool plugins (hkj-gradle-plugin and hkj-maven-plugin), and extends Spring MVC with virtual-thread-native return value handlers for VTaskPath and VStreamPath.
- WriterT: Monad transformer for output accumulation across effect boundaries, wrapping
Kind<F, Pair<A, W>>with automatic Monoid-based combining duringflatMapchains - MonadWriter: MTL-style capability interface with
tell,listen,pass,listens, andcensorfor output accumulation - MonadReader: MTL-style capability interface with
ask,local,reader, andasksfor shared environment access - MonadState: MTL-style capability interface with
get,put,modify, andgetsfor stateful computation - par(): Parallel/applicative composition for
ForandForPathcomprehensions; true concurrency onVTask, intent-documenting on sequential monads - traverse/sequence/flatTraverse: Bulk effectful operations within comprehension chains: apply an effectful function across a structure, flip
Structure<Effect<A>>toEffect<Structure<A>>, or traverse-and-flatten in one step - For-Comprehension Optics Integration:
through(Iso)for type-safe value conversion inFor;traverseOver(),modifyThrough(),modifyVia(), andupdateVia()for optics-driven state operations inForState - Fold Combinators:
Fold.plus(),Fold.empty(), andFold.sum()forming a monoid on folds for multi-path data extraction - Compile-Time Path Checks:
hkj-checkerjavac plugin detecting Path type mismatches at compile time forvia,then,zipWith,zipWith3,recoverWith, andorElse - Build Plugins:
hkj-gradle-plugin(one-line Gradle setup) andhkj-maven-plugin(Maven lifecycle extension) that auto-configure HKJ dependencies,--enable-previewflags, compile-time checking, and optional Spring Boot integration - hkj-bom: Bill of Materials POM for version-aligned dependency management across all HKJ modules in both Gradle and Maven
- Diagnostics:
hkjDiagnosticsGradle task andmvn hkj:diagnosticsgoal reporting active dependencies, compiler arguments, and checks - VTaskPath Spring MVC:
VTaskPathReturnValueHandlerconverting controller return values to asyncDeferredResultresponses on virtual threads - VStreamPath SSE:
VStreamPathReturnValueHandlerconverting controller return values to Server-Sent Events with pull-based backpressure, no Reactor required - Dependency updates: Gradle 9.4.0, JUnit 6.0.3, Jackson 3.1.0, Spring Boot 4.0.3, jOOQ 3.20.11, javapoet 0.12.0, and others
- Faster
FunctionValidatorandKindValidatorwith simplified implementation - Test reliability improvements: replaced
Thread.sleepwith Awaitility across test suite
v0.3.6 (6 March 2026)
VStream Lazy Streaming, Resilience Patterns, and ForState Comprehensions
This release introduces VStream, a lazy pull-based streaming type built on virtual threads with full HKT integration, adds four core resilience patterns (Circuit Breaker, Bulkhead, Retry, Saga) with Effect Path integration, extends ForState with filtering and pattern matching, and delivers a Market Data Pipeline capstone example.
- VStream: Lazy pull-based streaming on virtual threads with
Stepprotocol (Emit/Done/Skip), factory methods (of,range,iterate,generate,unfold), transformation combinators, and error recovery - VStream HKT Integration:
VStreamKindwitness type with Functor, Applicative, Monad, Foldable, Traverse, and Alternative type class instances - VStream Parallel Operations:
VStreamParwithparEvalMap,parEvalMapUnordered,parEvalFlatMap,merge,parCollect, and chunking combinators - VStream Resources:
bracket/onFinalizeresource lifecycle management andVStreamReactivebidirectionalFlow.Publisherbridge with backpressure - VStreamPath: Effect Path bridge with factory methods,
PathOpsoperations, terminal operations bridging toVTaskPath, and optics focus bridge - Circuit Breaker: State machine (Closed/Open/HalfOpen) with configurable failure thresholds and recovery timeouts
- Bulkhead: Concurrency limiting for isolating resource access
- Retry: Configurable retry policies with fixed delay, exponential backoff, and jitter
- Saga: Distributed transaction compensation with ordered rollback
- Combined Resilience: Composing multiple resilience patterns and Path API ergonomic methods:
retry(),circuitBreaker(),bulkhead(),timeout() - ForState: Filtering (
when), pattern matching (matchThen), traversals, zoom, andtoState()bridge from For comprehensions at all arities (1–12) - traverseWith(): Parallel effectful optics traversal for
FocusPath,AffinePath, andTraversalPathviaVTaskPathandStructuredTaskScope - Market Data Pipeline: 14-feature capstone example demonstrating concurrent feed merging, parallel enrichment, risk assessment, windowed aggregation, anomaly detection, and circuit breaker failover
- Refreshed Monads chapter with problem-first structure, real-world analogies, and consistent formatting
FunctionValidatoroptimisation: deferred error-message construction avoidsStringallocation on the happy path; fixed Gradle benchmark commands (-Pincludes)- Javadoc generation fix to include annotation-processor-generated sources (
Tuple2–Tuple12,MonadicSteps, etc.) - JMH benchmarks for VStream construction, combinators, terminals, and parallel operations
v0.3.5 (15 February 2026)
Extended For-Comprehensions, VTask API Refinement, and Documentation Restructure
This release extends for-comprehension arity to 12, simplifies the VTask API, adds Maybe-to-Either conversions, upgrades to JUnit 6, and delivers a comprehensive documentation restructure with quickstart guides, cheat sheets, migration cookbooks, and railway diagrams.
- For-Comprehension Arity 12:
ForandForPathnow support up to 12 monadic bindings (previously 5), with generatedTuple9–Tuple12andFunction9–Function12 - VTask API:
VTask.run()no longer declaresthrows Throwable; checked exceptions are wrapped inVTaskExecutionException - Maybe.toEither: New
toEither(L)andtoEither(Supplier<L>)conversion methods for seamlessMaybe→Eithertransitions - Quickstart: New getting-started guide with Gradle and Maven setup including
--enable-previewconfiguration - Cheat Sheet: Quick-reference for Path types, operators, escape hatches, and type conversions
- Stack Archetypes: 7 named transformer stack archetypes with colour-coded railway diagrams
- Migration Cookbook: 6 recipes for migrating from try/catch, Optional chains, null checks, CompletableFuture, validation, and nested records
- Compiler Error Guide: Solutions for the 5 most common Effect Path compiler errors
- Effects-Optics Capstone: Combined effects and optics pipeline example
- Railway operator diagrams for all 8 Effect Path operators and for EitherT, MaybeT, OptionalT transformers
- JUnit 6.0.2 upgrade (from 5.14.1) across all test modules
- Golden file test infrastructure with automated sync verification and pitest mutation coverage improvements
v0.3.4 (31 January 2026)
External Type Optics and Examples Gallery
This release introduces powerful optics generation for external types you cannot modify, plus a new Examples Gallery chapter documenting all runnable examples.
- @ImportOptics: Generate optics for JDK classes and third-party library types via auto-detection of withers and accessors
- Spec Interfaces: Fine-grained control over external type optics with
OpticsSpec<S>for complex types like Jackson'sJsonNode - @ThroughField Auto-Detection: Automatic traversal type detection for
List,Set,Optional, arrays, andMapfields - Examples Gallery: New chapter with categorised, runnable examples demonstrating core types, transformers, Effect Path API, and optics
- Comprehensive hkj-processor testing improvements with enhanced coverage
v0.3.3 (24 January 2026)
Structured Concurrency, Atomic Optics, and Enhanced Examples
This release introduces structured concurrency primitives, atomic coupled-field updates, and a comprehensive Order Workflow example demonstrating these patterns.
- Structured Concurrency:
Scopefor parallel operations withallSucceed(),anySucceed(),firstComplete(), andaccumulating()joiners - Resource Management:
Resourcefor bracket-pattern cleanup with guaranteed release - Coupled Fields:
Lens.pairedfor atomic multi-field updates bypassing invalid intermediate states - Order Workflow Overview: Reorganised documentation with focused sub-pages
- Concurrency and Scale: Context, Scope, Resource, VTaskPath patterns in practice
EnhancedOrderWorkflow: Full workflow demonstrating Context, Scope, Resource, VTaskPathOrderContext: ScopedValue keys for trace ID, tenant isolation, and deadline enforcement- Scope & Resource Tutorials: 18 exercises on concurrency patterns
- Release History: New page documenting all releases
v0.3.2 (17 January 2026)
Virtual Thread Concurrency with VTask
This release introduces VTask<A>, a lazy computation effect leveraging Java 25's virtual threads for lightweight concurrent programming.
- VTask: Lazy computation effect for virtual thread execution
- Structured Concurrency:
Scopefor parallel operations withallSucceed(),anySucceed(), andaccumulating()patterns - Resource Management:
Resourcefor bracket-pattern cleanup guarantees - VTaskPath: Integration with the Effect Path API
- Concurrency and Scale: Practical patterns in the Order Workflow example
Parparallel combinators for concurrent execution- Comprehensive benchmarks comparing virtual vs. platform threads
v0.3.1 (15 January 2026)
Static Analysis Utilities
This release adds utilities for statically analysing Free Applicative and Selective functors without execution.
- Choosing Abstraction Levels: Guide to selecting Functor, Applicative, Selective, or Monad
- Free Applicative: Static analysis with
FreeApAnalyzer - Selective: Conditional effects with
SelectiveAnalyzer - Tutorial 11 on static analysis patterns
v0.3.0 (4 January 2026)
Effect Path Focus Integration
Major release introducing the unified Effect Path API and Focus DSL integration. Requires Java 25 baseline.
- Effect Path Overview: The railway model for composable effects
- Path Types: 17+ composable Path types including
EitherPath,MaybePath,IOPath - Focus DSL: Type-safe optics with annotation-driven generation
- Focus-Effect Integration: Bridge between optics and effects
- ForPath Comprehension: For-comprehension syntax for Path types
- Spring Boot Integration: Spring Boot 4.0.1+ support
- Order Workflow: Complete example demonstrating Effect Path patterns
Earlier Releases
v0.2.8 (26 December 2025)
- Introduced
ForPathfor Path-native for-comprehension syntax - Complete Spring Boot 4.0.1 migration of
hkj-springfromEitherTto Effect Path API - New return value handlers for Spring integration
v0.2.7 (20 December 2025)
- Effect Contexts:
ErrorContext,OptionalContext,ConfigContext,MutableContext - Bridge API enabling seamless transitions between optics and effects
v0.2.6 (19 December 2025)
- New Effect Path API with 17+ Path types
- Retry policies and parallel execution utilities
- Kind field support in Focus DSL
v0.2.5 (9 December 2025)
- Annotation-driven Focus DSL for fluent optics composition
- Free Applicative and Coyoneda functors
- Natural Transformation support
v0.2.4 (3 December 2025)
- Affine optic for focusing on zero or one element
ForTraversal,ForState, andForIndexedcomprehension builders- For-comprehension and optics integration
v0.2.3 (1 December 2025)
- Cross-optic composition (Lens + Prism → Traversal)
- Experimental Spring Boot starter
- Custom target package support for annotation processor
v0.2.2 (29 November 2025)
- Java 25 baseline
- Experimental
hkj-springmodule - Validation helpers and ArchUnit architecture tests
- Thread-safety fix in Lazy memoisation
v0.2.1 (23 November 2025)
- 7-part Core Types tutorial series
- 9-part Optics tutorial (~150 minutes total)
- Versioned documentation system
- Property-based testing infrastructure
- JMH benchmarking framework
v0.2.0 (21 November 2025)
- Six new optic types: Fold, Getter, Setter, and indexed variants
- FreeMonad for DSL construction
- Trampoline for stack-safe recursion
- Const Functor
- Enhanced Monoid with new methods
- Alternative type class
v0.1.9 (14 November 2025)
- Selective type class for conditional effects
- Enhanced optics with
modifyWhen()andmodifyBranch() - Bifunctor for Either, Tuple2, Validated, and Writer
- Higher-kinded Stream support
v0.1.8 (9 September 2025)
- Profunctor type class
- Profunctor operations in universal Optic interface
v0.1.7 (29 August 2025)
- Generated
with*helper methods for records via@GenerateLenses Traversals.forMap()for key-specific Map operations- Semigroup interface with Monoid extending it
- Validated Applicative with error accumulation
v0.1.6 (14 July 2025)
- Optics introduction: Lens, Iso, Prism, and Traversals
- Annotation-based optics generation
- Plugin architecture for extending Traversal types
- Modular release structure
v0.1.5 (12 June 2025)
- For comprehension with generators, bindings, guards, and yield
- Tuple1-5 and Function5 support
v0.1.4 (5 June 2025)
- Validated Monad
- Standardised widen/narrow pattern for KindHelpers (breaking change)
v0.1.3 (31 May 2025)
- First Maven Central publication
- 12 monads, 5 transformers
- Comprehensive documentation
v0.1.0 (3 May 2025)
- Initial release
- Core types: Either, Try, CompletableFuture, IO, Lazy, Reader, State, Writer
- EitherT transformer
- GitHub Releases: Full changelogs and assets
- Contributing: How to contribute to Higher-Kinded-J
Previous: Glossary Next: Benchmarks & Performance