λ dmx-fun
Explicit types for failures, absence, and validation in Java.
dmx-fun is a Java library that makes failures, absence, and validation
explicit in the type system. Instead of throwing exceptions or returning
null, operations return values that encode both the happy path and the error
case — composable via map and flatMap, pattern-matchable via
sealed interfaces, and testable without mocks.
The core library has a single mandatory dependency: JSpecify for null-safety annotations. Everything else is optional.
Types
Eight composable types — each with a clear purpose, a consistent API, and a guide page.
Option<T> Nullability A value that may or may not be present. The null-safe alternative.
Result<V, E> Error handling Either a success value or a typed error. Models domain failures explicitly.
Try<V> Exception handling Wraps a computation that may throw. Turns exceptions into values.
Validated<E, A> Validation Like Result but accumulates multiple errors instead of failing fast.
Either<L, R> Disjoint union A neutral disjoint union with no success/failure semantics.
Lazy<T> Deferred computation A value computed at most once, on first access. Thread-safe memoization.
Tuple2/3/4 Product types Typed heterogeneous tuples. Named fields without a dedicated class.
NonEmptyList<T> Collections A list guaranteed to have at least one element at compile time.
Optional modules
Independent dependencies — add only what you need.
fun-jackson JSON Serializers and deserializers for all dmx-fun types via Jackson.
codes.domix:fun-jackson fun-assertj Testing Fluent AssertJ custom assertions for all dmx-fun types.
codes.domix:fun-assertj fun-spring Spring Transaction support for Result, Try, and Validated. Rolls back on error without throwing exceptions.
codes.domix:fun-spring Installation
Available on Maven Central. See the Getting Started page for full coordinates.
implementation("codes.domix:fun:LATEST_VERSION")<dependency> <groupId>codes.domix</groupId> <artifactId>fun</artifactId> <version>LATEST_VERSION</version></dependency>Quick example
import dmx.fun.Option;import dmx.fun.Try;import java.util.function.Function;
public class QuickExample { record User(String name, String email, String password) { }
Function<String, Option<User>> findUser = email -> Option.some(new User("User", email, "secret"));
private String getUserName(String email) { // Handle options safely return findUser.apply(email) .map(User::name) .getOrElse("Anonymous"); }
private void parseInt(String name) { // Handle errors functionally Try.of(() -> Integer.parseInt(name)) .recover(throwable -> { System.out.println("Error parsing: " + throwable.getMessage()); return 0; }) .onSuccess(System.out::println); }}Ready to dive in?
The Developer Guide covers every type in depth — design rationale, every combinator, composition patterns, and pitfalls to avoid.