Appendix A: Pragmatica Core API Reference
Library Information
Maven:
<dependency>
<groupId>org.pragmatica-lite</groupId>
<artifactId>core</artifactId>
<version>1.0.0-rc1</version>
</dependency>
Gradle:
implementation 'org.pragmatica-lite:core:1.0.0-rc1'
Documentation: https://central.sonatype.com/artifact/org.pragmatica-lite/core
Type Conversions
Option Conversions
| From | To | Method |
|---|---|---|
Option<T> |
Result<T> |
.toResult(Cause cause) or .await(Cause cause) |
Option<T> |
Result<T> |
.toResult() (uses CoreError.emptyOption) |
Option<T> |
Promise<T> |
.async(Cause cause) |
Option<T> |
Promise<T> |
.async() (uses CoreError.emptyOption) |
Option<T> |
Optional<T> |
.toOptional() |
Result Conversions
| From | To | Method |
|---|---|---|
Result<T> |
Option<T> |
.option() (loses error) |
Result<T> |
Promise<T> |
.async() |
Promise Conversions
| From | To | Method |
|---|---|---|
Promise<T> |
Promise<T> |
.async() (identity) |
Promise<T> |
Result<T> |
.await() (blocks) |
Promise<T> |
Result<T> |
.await(TimeSpan timeout) |
Cause Conversions
| From | To | Method |
|---|---|---|
Cause |
Result<T> |
.result() |
Cause |
Promise<T> |
.promise() |
Creating Instances
Option
Option.some(value) // Create present option
Option.present(value) // Alias for some()
Option.none() // Create empty option
Option.empty() // Alias for none()
Option.option(nullable) // null -> none, value -> some
Option.from(Optional<T>) // Convert Java Optional
Result
Result.success(value) // Create success
Result.ok(value) // Alias for success()
Result.unitResult() // Success with Unit value
Result.failure(cause) // Create failure (prefer cause.result())
Result.err(cause) // Alias for failure()
Promise
Promise.success(value) // Resolved success
Promise.ok(value) // Alias for success()
Promise.unitPromise() // Resolved with Unit
Promise.failure(cause) // Resolved failure (prefer cause.promise())
Promise.resolved(Result<T> result) // Resolved from result
Promise.promise() // Unresolved promise
Promise.promise(Consumer<Promise<T>>) // Unresolved, runs consumer async
Promise.promise(Supplier<Result<T>>) // Async execution of supplier
Exception Handling (lift methods)
Result.lift
// Basic lift
Result.lift(ThrowingFn0<U> supplier)
Result.lift(Fn1<Cause, Throwable> mapper, ThrowingFn0<U> supplier)
Result.lift(ThrowingRunnable runnable) // Returns Result<Unit>
Result.lift(Cause cause, ThrowingFn0<U> supplier) // Fixed cause
// Direct invocation (lift + apply)
Result.lift1(ThrowingFn1<R, T1> fn, T1 value)
Result.lift2(ThrowingFn2<R, T1, T2> fn, T1 v1, T2 v2)
Result.lift3(ThrowingFn3<R, T1, T2, T3> fn, T1 v1, T2 v2, T3 v3)
// Function factories (returns wrapped function)
Result.liftFn1(ThrowingFn1<R, T1> fn) // Returns Fn1<Result<R>, T1>
Result.liftFn2(ThrowingFn2<R, T1, T2> fn)
Result.liftFn3(ThrowingFn3<R, T1, T2, T3> fn)
Promise.lift
// Basic lift (async execution)
Promise.lift(ThrowingFn0<U> supplier)
Promise.lift(Fn1<Cause, Throwable> mapper, ThrowingFn0<U> supplier)
Promise.lift(ThrowingRunnable runnable) // Returns Promise<Unit>
// Direct invocation (async)
Promise.lift1(ThrowingFn1<R, T1> fn, T1 value)
Promise.lift2(ThrowingFn2<R, T1, T2> fn, T1 v1, T2 v2)
Promise.lift3(ThrowingFn3<R, T1, T2, T3> fn, T1 v1, T2 v2, T3 v3)
// Function factories
Promise.liftFn1(ThrowingFn1<R, T1> fn) // Returns Fn1<Promise<R>, T1>
Aggregation (all/any/allOf)
Result.all (accumulates failures)
Result.all(Result<T1>) // -> Mapper1<T1>
Result.all(Result<T1>, Result<T2>) // -> Mapper2<T1, T2>
// ... up to Mapper9
Result.allOf(Result<T>...) // -> Result<List<T>>
Result.allOf(List<Result<T>>) // -> Result<List<T>>
Promise.all (fail-fast)
Promise.all(Promise<T1>) // -> Mapper1<T1>
Promise.all(Promise<T1>, Promise<T2>) // -> Mapper2<T1, T2>
// ... up to Mapper9
Promise.allOf(Collection<Promise<T>>) // -> Promise<List<Result<T>>>
any Methods
Option.any(Option<T>...) // First present option
Result.any(Result<T>...) // First success result
Promise.any(Promise<T>...) // First success, cancels others
Common Methods
map/flatMap
// All types
.map(Fn1<U, T> mapper) // Transform value
.map(Supplier<U> supplier) // Replace value
.flatMap(Fn1<M<U>, T> mapper) // Chain monadic operations
.flatMap(Supplier<M<U>> supplier) // Replace with monadic value
// Result/Promise only
.flatMap2(Fn2<M<U>, T, I> mapper, I param) // flatMap with extra param
.mapToUnit() // Transform to Unit
filter (Result and Promise)
.filter(Cause cause, Predicate<T> predicate)
.filter(Fn1<Cause, T> causeMapper, Predicate<T> predicate)
Callback Methods
// Option
.onPresent(Consumer<T>)
.onEmpty(Runnable)
.apply(Consumer<T>, Runnable) // Bifurcation
// Result
.onSuccess(Consumer<T>)
.onFailure(Consumer<Cause>)
.onResult(Consumer<Result<T>>)
.apply(Consumer<T>, Consumer<Cause>) // Bifurcation
// Promise (same as Result, plus async variants)
.onSuccessAsync(Consumer<T>)
.onFailureAsync(Consumer<Cause>)
.withSuccess(Consumer<T>) // Returns self for chaining
fold
// Option
.fold(Supplier<R> empty, Fn1<R, T> present)
// Result/Promise
.fold(Fn1<R, Cause> failure, Fn1<R, T> success)
Recovery
.or(T replacement) // Fallback value
.or(Supplier<T> supplier) // Lazy fallback
.orElse(M<T> replacement) // Fallback monadic value
.recover(Fn1<T, Cause> mapper) // Result/Promise: recover from failure
Verify.Is Predicates
// Null check
Verify.Is::notNull
// Presence check (CharSequence)
Verify.Is::present // Not null and not blank
// String checks
Verify.Is::empty
Verify.Is::notEmpty
Verify.Is::blank
Verify.Is::notBlank
Verify.Is::lenBetween // lenBetween(8, 128)
Verify.Is::contains
Verify.Is::notContains
Verify.Is::matches // matches(Pattern)
// Numeric checks
Verify.Is::positive
Verify.Is::negative
Verify.Is::nonNegative
Verify.Is::nonPositive
Verify.Is::greaterThan
Verify.Is::lessThan
Verify.Is::between // between(0, 150)
Verify.Is::equalTo
Verify.Is::notEqualTo
Usage:
Verify.ensure(password, Verify.Is::lenBetween, 8, 128)
Verify.ensure(age, Verify.Is::between, 0, 150)
Parse Subpackage
Number Parsing
Number.parseInt(String) // -> Result<Integer>
Number.parseLong(String) // -> Result<Long>
Number.parseDouble(String) // -> Result<Double>
Number.parseBigDecimal(String) // -> Result<BigDecimal>
DateTime Parsing
DateTime.parseLocalDate(String) // -> Result<LocalDate>
DateTime.parseLocalTime(String) // -> Result<LocalTime>
DateTime.parseLocalDateTime(String) // -> Result<LocalDateTime>
DateTime.parseInstant(String) // -> Result<Instant>
Network Parsing
Network.parseUUID(String) // -> Result<UUID>
Network.parseURL(String) // -> Result<URL>
Network.parseURI(String) // -> Result<URI>
Causes Utilities
Causes.cause(String message) // Simple cause
Causes.cause(String message, Option<Cause> source) // Cause with source
Causes.fromThrowable(Throwable) // Convert exception
Causes.forOneValue(String template) // Fn1<Cause, T> factory
Causes.forTwoValues(String template) // Fn2<Cause, T1, T2>
Causes.forThreeValues(String template) // Fn3<Cause, T1, T2, T3>
Causes.composite(Result<?>...) // Composite from results
Template syntax (uses String.format):
Causes.forOneValue("Invalid email: %s") // CORRECT
Causes.forTwoValues("Range error: %s to %s") // CORRECT
Promise-Specific Operations
// Resolution
.resolve(Result<T>) // Resolve unresolved promise
.succeed(T value) // Resolve with success
.fail(Cause cause) // Resolve with failure
.cancel() // Cancel execution
// Query
.isResolved() // Check if resolved
// Timeout
.timeout(TimeSpan duration) // Add timeout
// Result manipulation
.mapResult(Fn1<Result<U>, Result<T>>) // Transform result
.trace(Fn1<Cause, Cause>) // Transform error (alias: mapError)
Example Usage Patterns
Adapter with exception handling
public Promise<User> findUser(UserId id) {
return Promise.lift(
CoreError::database,
() -> jdbcTemplate.queryForObject(
"SELECT * FROM users WHERE id = ?",
new Object[]{id.value()},
this::mapUser)
);
}
Lifting sync Result to async Promise
public Promise<Response> execute(Request request) {
return ValidRequest.validRequest(request) // Result<ValidRequest>
.async() // Promise<ValidRequest>
.flatMap(step1::apply)
.flatMap(step2::apply);
}
Testing with functional assertions
@Test
void validation_fails_forInvalidInput() {
ValidRequest.validRequest(invalidRequest)
.onSuccess(Assertions::fail);
}
@Test
void validation_succeeds_forValidInput() {
ValidRequest.validRequest(validRequest)
.onFailure(Assertions::fail)
.onSuccess(valid -> {
assertEquals("expected", valid.field());
});
}