View Javadoc
1   package com.guinetik.hexafun.fun;
2   
3   import java.util.Objects;
4   import java.util.function.Function;
5   
6   public sealed interface Result<T> permits Result.Success, Result.Failure {
7   
8       static <T> Result<T> ok(T value) {
9           return new Success<>(value);
10      }
11  
12      static <T> Result<T> fail(String message) {
13          return new Failure<>(message);
14      }
15  
16      boolean isSuccess();
17      boolean isFailure();
18  
19      T get(); // orElseThrow?
20      String error();
21  
22      <U> Result<U> map(Function<T, U> mapper);
23      <U> Result<U> flatMap(Function<T, Result<U>> mapper);
24  
25      <U> U fold(Function<String, U> onFailure, Function<T, U> onSuccess);
26  
27      final class Success<T> implements Result<T> {
28          private final T value;
29  
30          public Success(T value) {
31              this.value = value;
32          }
33  
34          public boolean isSuccess() { return true; }
35          public boolean isFailure() { return false; }
36          public T get() { return value; }
37          public String error() { throw new IllegalStateException("No error"); }
38  
39          public <U> Result<U> map(Function<T, U> mapper) {
40              return Result.ok(mapper.apply(value));
41          }
42  
43          public <U> Result<U> flatMap(Function<T, Result<U>> mapper) {
44              return mapper.apply(value);
45          }
46  
47          public <U> U fold(Function<String, U> onFailure, Function<T, U> onSuccess) {
48              return onSuccess.apply(value);
49          }
50      }
51  
52      final class Failure<T> implements Result<T> {
53          private final String error;
54  
55          public Failure(String error) {
56              this.error = Objects.requireNonNull(error);
57          }
58  
59          public boolean isSuccess() { return false; }
60          public boolean isFailure() { return true; }
61          public T get() { throw new IllegalStateException(error); }
62          public String error() { return error; }
63  
64          public <U> Result<U> map(Function<T, U> mapper) {
65              return Result.fail(error);
66          }
67  
68          public <U> Result<U> flatMap(Function<T, Result<U>> mapper) {
69              return Result.fail(error);
70          }
71  
72          public <U> U fold(Function<String, U> onFailure, Function<T, U> onSuccess) {
73              return onFailure.apply(error);
74          }
75      }
76  }