Package com.guinetik.corefun
Class Result<S,F>
java.lang.Object
com.guinetik.corefun.Result<S,F>
- Type Parameters:
S- the type of the success valueF- the type of the failure value
A functional container representing either a success or failure outcome.
Result is an Either-style monad that encapsulates either a successful value
or an error, providing a functional approach to error handling without exceptions.
This eliminates the need for null checks and exception handling in business logic,
promoting cleaner, more composable code.
Key Features
- Type-safe error handling - Errors are part of the type signature
- Functional composition - Chain operations with
map(java.util.function.Function<? super S, ? extends T>)andflatMap(java.util.function.Function<? super S, com.guinetik.corefun.Result<T, F>>) - Pattern matching - Use
fold(java.util.function.Function<? super F, ? extends R>, java.util.function.Function<? super S, ? extends R>)to handle both cases uniformly - Validation support - Combine with
validate(java.util.function.Function<? super S, java.lang.Boolean>, java.util.function.Function<? super S, ? extends F>)for input validation - Recovery - Handle failures gracefully with
recover(java.util.function.Function<? super F, com.guinetik.corefun.Result<S, F>>)
Example Usage
Result<User, String> result = findUser(id);
// Pattern matching with fold
String message = result.fold(
error -> "Error: " + error,
user -> "Found: " + user.getName()
);
// Chaining operations
Result<String, String> greeting = result
.map(user -> user.getName())
.map(name -> "Hello, " + name);
// Validation
Result<Integer, String> validAge = Result.success(age)
.validate(a -> a >= 0 && a <= 150, a -> "Invalid age: " + a);
// Recovery from errors
Result<User, String> userOrGuest = findUser(id)
.recover(error -> Result.success(guestUser));
- Since:
- 0.1.0
- Author:
- Guinetik <guinetik@gmail.com>
- See Also:
-
Method Summary
Modifier and TypeMethodDescriptionstatic <S,F> Result<S, F> failure(F error) Creates a failed Result containing the given error.Transforms the success value with a function that returns a Result.abstract <R> RApplies one of two functions depending on the Result state.abstract Sget()Gets the success value.abstract FgetError()Gets the failure value.abstract SReturns the success value or a default if this is a failure.abstract SgetOrElseGet(Supplier<? extends S> supplier) Returns the success value or computes a default if this is a failure.abstract booleanReturns true if this Result represents a failure.abstract booleanReturns true if this Result represents a success.Transforms the success value using the provided function.mapFailure(Function<? super F, ? extends E> mapper) Transforms the failure value using the provided function.Performs an action on the value (success or failure) without altering the Result.peekFailure(Consumer<? super F> action) Performs an action on the failure value if present.peekSuccess(Consumer<? super S> action) Performs an action on the success value if present.Recovers from a failure by applying a function that returns a new Result.Converts a list of Results into a Result of a list.static <S,F> Result<S, F> success(S value) Creates a successful Result containing the given value.Applies a function to each element and sequences the results.Validates the success value against a predicate.
-
Method Details
-
success
Creates a successful Result containing the given value.- Type Parameters:
S- success typeF- failure type- Parameters:
value- the success value- Returns:
- a successful Result
-
failure
Creates a failed Result containing the given error.- Type Parameters:
S- success typeF- failure type- Parameters:
error- the failure value- Returns:
- a failed Result
-
isSuccess
public abstract boolean isSuccess()Returns true if this Result represents a success.- Returns:
- true if success, false if failure
-
isFailure
public abstract boolean isFailure()Returns true if this Result represents a failure.- Returns:
- true if failure, false if success
-
get
Gets the success value. Throws if this is a failure.- Returns:
- the success value
- Throws:
IllegalStateException- if this is a failure
-
getError
Gets the failure value. Throws if this is a success.- Returns:
- the failure value
- Throws:
IllegalStateException- if this is a success
-
fold
public abstract <R> R fold(Function<? super F, ? extends R> onFailure, Function<? super S, ? extends R> onSuccess) Applies one of two functions depending on the Result state. This is the primary way to extract values from a Result.Example:
String message = result.fold( error -> "Failed: " + error, value -> "Success: " + value );- Type Parameters:
R- the return type- Parameters:
onFailure- function to apply if failureonSuccess- function to apply if success- Returns:
- the result of applying the appropriate function
-
map
Transforms the success value using the provided function. If this is a failure, returns a new failure with the same error.- Type Parameters:
T- the new success type- Parameters:
mapper- function to transform the success value- Returns:
- a new Result with the transformed value
-
flatMap
Transforms the success value with a function that returns a Result. Useful for chaining operations that might fail.Example:
Result<User, String> user = findUser(id); Result<Account, String> account = user.flatMap(u -> findAccount(u.getAccountId()));- Type Parameters:
T- the new success type- Parameters:
mapper- function that returns a Result- Returns:
- the Result from the mapper, or a failure
-
mapFailure
Transforms the failure value using the provided function.- Type Parameters:
E- the new failure type- Parameters:
mapper- function to transform the failure value- Returns:
- a new Result with the transformed failure
-
getOrElse
Returns the success value or a default if this is a failure.- Parameters:
defaultValue- the default to return on failure- Returns:
- success value or default
-
getOrElseGet
Returns the success value or computes a default if this is a failure.- Parameters:
supplier- supplies the default value- Returns:
- success value or computed default
-
recover
Recovers from a failure by applying a function that returns a new Result.Example:
Result<User, String> user = findUser(id) .recover(error -> findGuestUser());- Parameters:
handler- function to handle the failure- Returns:
- this if success, or the result of the handler
-
validate
public abstract Result<S,F> validate(Function<? super S, Boolean> predicate, Function<? super S, ? extends F> failureProducer) Validates the success value against a predicate. If validation fails, produces a failure using the provided function.- Parameters:
predicate- condition to testfailureProducer- produces failure value if predicate fails- Returns:
- this if valid, or a failure
-
peek
Performs an action on the value (success or failure) without altering the Result.- Parameters:
observer- consumer that receives the value- Returns:
- this Result unchanged
-
peekSuccess
Performs an action on the success value if present.- Parameters:
action- consumer for the success value- Returns:
- this Result unchanged
-
peekFailure
Performs an action on the failure value if present.- Parameters:
action- consumer for the failure value- Returns:
- this Result unchanged
-
sequence
Converts a list of Results into a Result of a list. Returns the first failure encountered, or a success containing all values.Example:
List<Result<Integer, String>> results = List.of( Result.success(1), Result.success(2), Result.success(3) ); Result<List<Integer>, String> combined = Result.sequence(results); // Success[[1, 2, 3]] List<Result<Integer, String>> withFailure = List.of( Result.success(1), Result.failure("oops"), Result.success(3) ); Result<List<Integer>, String> failed = Result.sequence(withFailure); // Failure[oops]- Type Parameters:
S- the success typeF- the failure type- Parameters:
results- the list of Results to sequence- Returns:
- a Result containing all success values, or the first failure
-
traverse
public static <T,S, Result<List<S>,F> F> traverse(List<T> items, Function<? super T, Result<S, F>> mapper) Applies a function to each element and sequences the results. This is equivalent to mapping each element to a Result and then sequencing.Example:
List<String> inputs = List.of("1", "2", "3"); Result<List<Integer>, String> parsed = Result.traverse(inputs, s -> { try { return Result.success(Integer.parseInt(s)); } catch (NumberFormatException e) { return Result.failure("Invalid number: " + s); } }); // Success[[1, 2, 3]] List<String> mixed = List.of("1", "bad", "3"); Result<List<Integer>, String> failed = Result.traverse(mixed, s -> ...); // Failure[Invalid number: bad]- Type Parameters:
T- the input element typeS- the success typeF- the failure type- Parameters:
items- the list of items to traversemapper- function that converts each item to a Result- Returns:
- a Result containing all success values, or the first failure
-