All tutorials
INTERMEDIATE20 parts · Est. 8 hours

Building a functional programming library in Java 21

Build jfp, a small dependency-free functional library for Java 21 — Option, Result, Validated, functors, monads, and monoids — with the laws that make each abstraction trustworthy, tested against a running government-scheme eligibility example.

JavaFunctional Programming
pC
Prashant Chaturvedi
Updated 2026-05-01
Start reading

Chapters

1

Why functional programming in Java?

Set up the jfp Gradle project and meet the problem this series solves — mutable, exception-driven eligibility code — before writing a single abstraction.

15 min•2026-03-30
2

Functions and composition

Give Fn1 its andThen, compose, and identity, then state the two laws — identity and associativity — that let you refactor pipelines without changing behavior.

20 min•2026-03-31
3

Pure functions and immutable data

What purity buys — substitution, testability, auditability — and how Java 21 records plus defensive copies give you immutable domain values without ceremony.

15 min•2026-04-02
4

Algebraic data types

Model eligibility outcomes as a sealed sum type — Eligible, Ineligible, ManualReview — and let pattern matching make alternatives explicit at the boundary.

15 min•2026-04-04
5

Option: absence as data

Build Option as a sealed Some|None type with map, flatMap, and fold — and use it where a missing land record is a valid state, not an error, never a null.

25 min•2026-04-05
6

Result and Either: errors as values

Model expected failures — registry timeouts, invalid identities, missing citizens — as Result<T, E> so the error channel is typed, composable, and visible.

25 min•2026-04-07
7

Functors: mapping inside a context

map is the whole idea of a functor — transform the value without touching the context — and its two laws are what make DTO-to-domain mapping safe to chain.

20 min•2026-04-09
8

Applicatives and validation

When checks are independent, chain-of-flatMap is wrong — it stops at the first failure. Validated accumulates every error through map2 and a Semigroup.

25 min•2026-04-10
9

Monads: sequencing dependent steps

flatMap exists because map cannot flatten — when each step returns a context like Result, monadic bind threads the value through and short-circuits on failure.

25 min•2026-04-12
10

The monad laws, tested

Left identity, right identity, and associativity — the three laws that make flatMap chains safe to refactor, tested for real against Option and Result.

20 min•2026-04-14
11

Kleisli composition for effectful functions

Ordinary compose stops working when every step returns Result — Kleisli composition reconnects A→Result<B,E> functions so registry chains stay flat.

15 min•2026-04-15
12

Semigroups and monoids

An associative combine plus an identity element — the two smallest algebra laws — let Validated merge errors and folds combine results without order anxiety.

20 min•2026-04-17
13

Folds, traversals, and sequencing

foldLeft collapses a collection, traverse turns List<Result<T,E>> into Result<List<T>,E>, and Validated.sequence gathers every document error at once.

20 min•2026-04-19
14

Lazy evaluation and memoization

Wrap expensive evidence lookups in Lazy so they run at most once and only when a rule actually needs them — call-by-need semantics in 30 lines.

15 min•2026-04-21
15

IO: effects at the boundary

An educational IO<T> that defers side effects until unsafeRun — the policy core stays pure while audit writes and event publication compose as values.

20 min•2026-04-22
16

Reader: explicit environments

A Reader<Environment, T> is a function waiting for its config — it threads policy versions, thresholds, and clocks through computations without globals.

15 min•2026-04-24
17

State: transitions without mutable globals

State<S, A> is a function S → (A, S) — a value plus a new state. Model application status transitions as composable steps instead of a mutable workflow field.

20 min•2026-04-26
18

Async boundaries

Interop with CompletableFuture and virtual threads instead of building a runtime — independent registry lookups run in parallel, dependent ones stay sequential.

20 min•2026-04-27
19

Java interoperability — when the JDK is already enough

Converters between jfp types and Optional, Stream, and CompletableFuture, plus the honest table of when to reach for the library versus plain Java.

15 min•2026-04-29
20

Capstone: an auditable scheme decision pipeline

Wire Option, Result, Validated, Reader, State, and IO into one eligibility flow — pure policy core, typed failures, deferred effects, complete audit trail.

30 min•2026-05-01

Other Series

Type to search the site.

↑↓ navigate⏎ openPowered by Pagefind