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();
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 }