summaryrefslogtreecommitdiff
path: root/src/main/java/moe/nea/pcj/Result.java
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-11-14 01:35:24 +0100
committerLinnea Gräf <nea@nea.moe>2024-11-14 01:35:24 +0100
commited8eb00566a5e3b7f2d5564d7977a4b3ec8fe5b3 (patch)
tree9f8418ce1f27634a5a5f37a07f57c45379584d87 /src/main/java/moe/nea/pcj/Result.java
parent94e30f7ffbafcdd188d09d8c7bf7e4794b650018 (diff)
downloadprofunctor-codecs-java-ed8eb00566a5e3b7f2d5564d7977a4b3ec8fe5b3.tar.gz
profunctor-codecs-java-ed8eb00566a5e3b7f2d5564d7977a4b3ec8fe5b3.tar.bz2
profunctor-codecs-java-ed8eb00566a5e3b7f2d5564d7977a4b3ec8fe5b3.zip
wip
Diffstat (limited to 'src/main/java/moe/nea/pcj/Result.java')
-rw-r--r--src/main/java/moe/nea/pcj/Result.java78
1 files changed, 51 insertions, 27 deletions
diff --git a/src/main/java/moe/nea/pcj/Result.java b/src/main/java/moe/nea/pcj/Result.java
index 8bec96a..e43633b 100644
--- a/src/main/java/moe/nea/pcj/Result.java
+++ b/src/main/java/moe/nea/pcj/Result.java
@@ -2,12 +2,15 @@ package moe.nea.pcj;
import org.jspecify.annotations.Nullable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
import java.util.Optional;
import java.util.function.Function;
public sealed interface Result<Good, Bad> permits Result.Ok, Result.Fail {
default boolean isOk() {
- return error().isEmpty();
+ return errors().isEmpty();
}
Optional<Good> value();
@@ -18,26 +21,31 @@ public sealed interface Result<Good, Bad> permits Result.Ok, Result.Fail {
return value().or(this::partial);
}
- Optional<Bad> error();
+ List<Bad> errors();
default <Next> Result<Next, Bad> map(Function<Good, Next> mapper) {
return flatMap(mapper.andThen(Result::ok));
}
- default <Next> Result<Next, Bad> flatMap(Function<Good, Result<Next, Bad>> mapper) {
- return flatMapBoth(mapper, Result::fail);
+ <Next> Result<Next, Bad> flatMap(Function<Good, Result<? extends Next, ? extends Bad>> mapper);
+
+ default <NextBad> Result<Good, NextBad> mapError(Function<Bad, NextBad> mapper) {
+ return mapErrors(it -> it.stream().map(mapper).toList());
}
- <NextGood> Result<NextGood, Bad> flatMapBoth(
- Function<Good, Result<NextGood, Bad>> mapGood,
- Function<Bad, Result<NextGood, Bad>> mapBad);
+ <NextBad> Result<Good, NextBad> mapErrors(Function<List<Bad>, List<NextBad>> mapper);
- Result<Good, Bad> appendError(Bad error);
+ Result<Good, Bad> appendErrors(List<Bad> error);
record Ok<Good, Bad>(Good okValue) implements Result<Good, Bad> {
@Override
- public Result<Good, Bad> appendError(Bad error) {
- return Result.partial(okValue, error);
+ public Result<Good, Bad> appendErrors(List<Bad> errors) {
+ return new Fail<>(okValue, errors);
+ }
+
+ @Override
+ public <NextBad> Result<Good, NextBad> mapErrors(Function<List<Bad>, List<NextBad>> mapper) {
+ return new Ok<>(okValue);
}
@Override
@@ -46,22 +54,26 @@ public sealed interface Result<Good, Bad> permits Result.Ok, Result.Fail {
}
@Override
- public Optional<Good> value() {
- return Optional.of(okValue);
+ public List<Bad> errors() {
+ return List.of();
}
@Override
- public Optional<Bad> error() {
- return Optional.empty();
+ public <Next> Result<Next, Bad> flatMap(Function<Good, Result<? extends Next, ? extends Bad>> mapper) {
+ return Result.cast(mapper.apply(okValue));
}
@Override
- public <NextGood> Result<NextGood, Bad> flatMapBoth(Function<Good, Result<NextGood, Bad>> mapGood, Function<Bad, Result<NextGood, Bad>> mapBad) {
- return mapGood.apply(okValue);
+ public Optional<Good> value() {
+ return Optional.of(okValue);
}
}
- record Fail<Good, Bad>(@Nullable Good partialValue, Bad badValue) implements Result<Good, Bad> {
+ record Fail<Good, Bad>(@Nullable Good partialValue, List<Bad> badValue) implements Result<Good, Bad> {
+ public Fail {
+ if (badValue.isEmpty())
+ throw new IllegalArgumentException("Cannot create failure without any error values");
+ }
@Override
public Optional<Good> value() {
@@ -74,22 +86,28 @@ public sealed interface Result<Good, Bad> permits Result.Ok, Result.Fail {
}
@Override
- public Optional<Bad> error() {
- return Optional.of(badValue);
+ public List<Bad> errors() {
+ return Collections.unmodifiableList(badValue);
}
@Override
- public <NextGood> Result<NextGood, Bad> flatMapBoth(Function<Good, Result<NextGood, Bad>> mapGood, Function<Bad, Result<NextGood, Bad>> mapBad) {
+ public <Next> Result<Next, Bad> flatMap(Function<Good, Result<? extends Next, ? extends Bad>> mapper) {
if (partialValue != null) {
- var nextPartial = mapGood.apply(partialValue);
- return nextPartial.appendError(badValue);
+ return Result.<Next, Bad>cast(mapper.apply(partialValue)).appendErrors(badValue);
}
- return mapBad.apply(badValue);
+ return new Fail<>(null, badValue);
+ }
+
+ @Override
+ public <NextBad> Result<Good, NextBad> mapErrors(Function<List<Bad>, List<NextBad>> mapper) {
+ return new Fail<>(partialValue, mapper.apply(badValue));
}
@Override
- public Result<Good, Bad> appendError(Bad error) {
- return Result.partial(partialValue, AppendableError.concatError(badValue, error));
+ public Result<Good, Bad> appendErrors(List<Bad> errors) {
+ var nextErrors = new ArrayList<>(badValue);
+ nextErrors.addAll(errors);
+ return new Fail<>(partialValue, nextErrors);
}
}
@@ -98,10 +116,16 @@ public sealed interface Result<Good, Bad> permits Result.Ok, Result.Fail {
}
static <Good, Bad> Result.Fail<Good, Bad> fail(Bad error) {
- return new Fail<>(null, error);
+ return new Fail<>(null, List.of(error));
+ }
+
+
+ static <Good, Bad> Result<Good, Bad> cast(Result<? extends Good, ? extends Bad> c) {
+ //noinspection unchecked
+ return (Result<Good, Bad>) c;
}
static <Good, Bad> Result.Fail<Good, Bad> partial(@Nullable Good partial, Bad error) {
- return new Fail<>(partial, error);
+ return new Fail<>(partial, List.of(error));
}
}