Aether FP provides type-safe, immutable functional programming primitives for Java 21 and beyond. It offers algebraic sum types and deferred computation containers that leverage modern Java features like sealed interfaces, pattern matching, and records.
All types are immutable and thread-safe, enforce a strict null prohibition policy, and compose naturally through map, flatMap, and fold operations. The library has zero runtime dependencies beyond JetBrains Annotations.
Note: Version < 1.0.0 indicates Aether Labs / experimental status with production-grade quality standards.
- Quick Start
- Installation
- Core Types
- Modules
- Documentation
- Building from Source
- Contributing
- Security
- License
<dependency>
<groupId>de.splatgames.aether.fp.labs</groupId>
<artifactId>aether-fp-core</artifactId>
<version>0.1.0</version>
</dependency>Gradle (Groovy / Kotlin)
// Groovy
implementation 'de.splatgames.aether.fp.labs:aether-fp-core:0.1.0'// Kotlin
implementation("de.splatgames.aether.fp.labs:aether-fp-core:0.1.0")import de.splatgames.aether.fp.types.Either;
import de.splatgames.aether.fp.types.Result;
import de.splatgames.aether.fp.types.Lazy;
// Either: right-biased sum type
Either<String, Integer> parsed = Either.right("42")
.map(Integer::parseInt);
// Result: success-biased operation outcome
Result<User, String> user = findUser(id)
.map(User::activate)
.recover(err -> User.guest());
// Lazy: thread-safe memoized computation
Lazy<Config> config = Lazy.of(() -> loadExpensiveConfig());
// Computed only on first access, cached foreverMaven
<dependency>
<groupId>de.splatgames.aether.fp.labs</groupId>
<artifactId>aether-fp-core</artifactId>
<version>0.1.0</version>
</dependency>Gradle (Groovy / Kotlin)
// Groovy
implementation 'de.splatgames.aether.fp.labs:aether-fp-core:0.1.0'// Kotlin
implementation("de.splatgames.aether.fp.labs:aether-fp-core:0.1.0")The Bill of Materials ensures consistent versions across all Aether FP modules.
Maven
<dependencyManagement>
<dependencies>
<dependency>
<groupId>de.splatgames.aether.fp.labs</groupId>
<artifactId>aether-fp-bom</artifactId>
<version>0.1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- No version needed -->
<dependency>
<groupId>de.splatgames.aether.fp.labs</groupId>
<artifactId>aether-fp-core</artifactId>
</dependency>
</dependencies>Gradle (Groovy / Kotlin)
// Groovy
dependencies {
implementation platform('de.splatgames.aether.fp.labs:aether-fp-bom:0.1.0')
implementation 'de.splatgames.aether.fp.labs:aether-fp-core'
}// Kotlin
dependencies {
implementation(platform("de.splatgames.aether.fp.labs:aether-fp-bom:0.1.0"))
implementation("de.splatgames.aether.fp.labs:aether-fp-core")
}A discriminated union representing exactly one of two possible values. By convention, left represents the error/alternative case and right represents the success/primary case.
Either<String, Integer> success = Either.right(42);
Either<String, Integer> failure = Either.left("not found");
// Right-biased map
Either<String, String> mapped = success.map(n -> "value: " + n);
// mapped = Right[value: 42]
// Chain with flatMap
Either<String, Integer> parsed = Either.<String, String>right("123")
.flatMap(s -> {
try {
return Either.right(Integer.parseInt(s));
} catch (NumberFormatException e) {
return Either.left("invalid number: " + s);
}
});
// Exhaustive pattern matching
String result = success.fold(
error -> "Error: " + error,
value -> "Success: " + value
);Key operations: map, flatMap, mapLeft, fold, swap, getOrElse, getOrElseGet, getOrElseThrow, ifLeft, ifRight
Purpose-built for modeling operations that may succeed or fail. Provides dedicated recovery operations and converts to Either for interoperability.
Result<Integer, String> success = Result.success(42);
Result<Integer, String> failure = Result.failure("not found");
// Success-biased composition
Result<String, String> mapped = success.map(n -> "value: " + n);
// Error recovery
Result<Integer, String> recovered = failure.recover(err -> 0);
// Convert to Either
Either<String, Integer> either = success.toEither();Key operations: map, flatMap, mapError, fold, recover, recoverWith, getOrElse, getOrElseGet, getOrElseThrow, toEither, ifSuccess, ifFailure
Wraps a Supplier and defers evaluation until the value is first accessed. Once evaluated, the result is cached permanently. Thread-safe via double-checked locking.
Lazy<String> lazy = Lazy.of(() -> expensiveComputation());
// lazy.isEvaluated() == false
String value = lazy.get(); // evaluates once
String same = lazy.get(); // returns cached value
// Compose lazily β no evaluation
Lazy<Integer> length = lazy.map(String::length);Key operations: get, map, flatMap, isEvaluated, ifEvaluated, toOptional
| Module | Description |
|---|---|
aether-fp-core |
Core FP types: Either, Result, Lazy |
aether-fp-bom |
Bill of Materials for version management |
Comprehensive documentation is available in the docs/ directory:
- π Getting Started β Installation and quick start guide
- π‘ Concepts β Sum types, null safety, biased composition, lazy evaluation, thread safety
- π Tutorials β Working with Either, Result, Lazy, and combining types
- π§ How-To Guides β Replace exceptions, replace null checks, chain operations, recover from errors
- π Examples β Validation pipelines, service layer patterns, configuration loading
- π Appendix β Glossary and quick reference
Prerequisites:
- Java 21+
- Maven 3.9.5+
# Build (skip tests)
mvn clean install -DskipTests
# Build with tests
mvn clean install
# QA profile (JaCoCo, SpotBugs, Checkstyle, OWASP, CycloneDX)
mvn verify -Pqa
# Integration tests
mvn verify -PitWe welcome contributions! Please see CONTRIBUTING.md for guidelines.
Please note that this project is released with a Code of Conduct. By participating in this project you agree to abide by its terms.
For security concerns, please see our Security Policy.
Do not report security vulnerabilities in public issues. See the security policy for responsible disclosure instructions.
MIT β see LICENSE.
Copyright (c) 2026 Splatgames.de Software and Contributors