From eb6b3704d0bdfc04d0d862d38140c100da2c09d5 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 1 Jan 2026 20:09:06 -0700 Subject: [PATCH] add linkedlist --- .../api/util/generic/data/LinkedList.java | 143 +++++++++++++ .../terra/api/util/generic/data/Monoid.java | 7 +- .../api/util/generic/data/Semigroup.java | 8 - .../api/util/generic/data/types/Either.java | 199 +++++++++--------- .../api/util/generic/data/types/Maybe.java | 165 ++++++++------- 5 files changed, 334 insertions(+), 188 deletions(-) create mode 100644 common/api/src/main/java/com/dfsek/terra/api/util/generic/data/LinkedList.java delete mode 100644 common/api/src/main/java/com/dfsek/terra/api/util/generic/data/Semigroup.java diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/LinkedList.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/LinkedList.java new file mode 100644 index 000000000..a14c925ce --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/LinkedList.java @@ -0,0 +1,143 @@ +package com.dfsek.terra.api.util.generic.data; + +import com.dfsek.terra.api.util.generic.control.Monad; +import com.dfsek.terra.api.util.generic.data.types.Maybe; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Function; + + +public sealed interface LinkedList extends Monad>, Monoid> { + @Override + LinkedList bind(Function>> map); + + @Override + default LinkedList pure(T1 t) { + return new Cons<>(t, empty()); + } + + @Override + LinkedList map(Function map); + + @Override + default LinkedList identity() { + return empty(); + } + + default Maybe head() { + return get(0); + } + + int length(); + + Maybe get(int index); + + LinkedList add(T value); + + > C toCollection(C collection); + + default List toList() { + return toCollection(new ArrayList<>()); + } + + default Set toSet() { + return toCollection(new HashSet<>()); + } + + @Override + LinkedList multiply(Monoid> t); + + static LinkedList of(T value) { + return new Cons<>(value, empty()); + } + + @SuppressWarnings("unchecked") + static Nil empty() { + return (Nil) Nil.INSTANCE; + } + + record Cons(T value, LinkedList tail) implements LinkedList { + @Override + public LinkedList bind(Function>> map) { + return ((LinkedList) map.apply(value)).multiply(tail.bind(map)); + } + + @Override + public LinkedList map(Function map) { + return new Cons<>(map.apply(value), tail.map(map)); + } + + @Override + public int length() { + return 1 + tail.length(); + } + + @Override + public Maybe get(int index) { + if(index == 0) return Maybe.just(value); + if(index > 0) return Maybe.nothing(); + return tail.get(index - 1); + } + + @Override + public LinkedList add(T value) { + return new Cons<>(value, tail.add(value)); + } + + @Override + public > C toCollection(C collection) { + collection.add(value); + return tail.toCollection(collection); + } + + @Override + public LinkedList multiply(Monoid> t) { + return new Cons<>(value, tail.multiply(t)); + } + } + + record Nil() implements LinkedList { + private static final Nil INSTANCE = new Nil<>(); + + @Override + @SuppressWarnings("unchecked") + public LinkedList bind(Function>> map) { + return (LinkedList) this; + } + + @Override + @SuppressWarnings("unchecked") + public LinkedList map(Function map) { + return (LinkedList) this; + } + + @Override + public int length() { + return 0; + } + + @Override + public Maybe get(int index) { + return Maybe.nothing(); + } + + @Override + public LinkedList add(T value) { + return new Cons<>(value, empty()); + } + + @Override + public > C toCollection(C collection) { + return collection; + } + + @Override + public LinkedList multiply(Monoid> t) { + return (LinkedList) t; + } + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/Monoid.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/Monoid.java index 7725067b8..ed5fb2334 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/Monoid.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/Monoid.java @@ -3,9 +3,8 @@ package com.dfsek.terra.api.util.generic.data; import com.dfsek.terra.api.util.generic.kinds.K; -public interface Monoid> extends Semigroup, K{ - > Monoid identity(); +public interface Monoid> extends K{ + Monoid identity(); - @Override - Monoid multiply(M t); + Monoid multiply(Monoid t); } diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/Semigroup.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/Semigroup.java deleted file mode 100644 index 26ec7f36f..000000000 --- a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/Semigroup.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.dfsek.terra.api.util.generic.data; - -import com.dfsek.terra.api.util.generic.kinds.K; - - -public interface Semigroup> extends K { - Semigroup multiply(S t); -} diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Either.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Either.java index 19291b4a7..37d1e11cc 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Either.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Either.java @@ -21,7 +21,7 @@ import java.util.function.Consumer; import java.util.function.Function; -public interface Either extends Monad>, BiFunctor> { +public sealed interface Either extends Monad>, BiFunctor> { default Either ifLeft(Consumer action) { return mapLeft(FunctionUtils.lift(action)); } @@ -77,115 +77,114 @@ public interface Either extends Monad>, BiFunctor FunctionUtils.sneakyThrow(l), Function.identity()); } - @SuppressWarnings({ "unchecked" }) @NotNull @Contract("_ -> new") static Either left(L1 left) { - record Left(L value) implements Either { - - @Override - @SuppressWarnings("unchecked") - public Either bind(Function>> map) { - return (Either) this; - } - - @Override - public Either mapLeft(Function f) { - return new Left<>(f.apply(value)); - } - - @SuppressWarnings({ "unchecked" }) - @Override - public Either mapRight(Function f) { - return (Either) this; - } - - @Override - public Maybe getLeft() { - return Maybe.just(value); - } - - @Override - public Maybe getRight() { - return Maybe.nothing(); - } - - @Override - public boolean isLeft() { - return true; - } - - @Override - public boolean isRight() { - return false; - } - - @Override - public Either flip() { - return right(value); - } - - @Override - public U collect(Function left, Function right) { - return left.apply(value); - } - } - return new Left<>(Objects.requireNonNull(left)); } - @SuppressWarnings({ "unchecked" }) @NotNull @Contract("_ -> new") static Either right(R1 right) { - record Right(R value) implements Either { - @Override - public Either bind(Function>> map) { - return (Either) map.apply(value); - } - - @SuppressWarnings({ "unchecked" }) - @Override - public Either mapLeft(Function f) { - return (Either) this; - } - - @Override - public Either mapRight(Function f) { - return new Right<>(f.apply(value)); - } - - @Override - public Maybe getLeft() { - return Maybe.nothing(); - } - - @Override - public Maybe getRight() { - return Maybe.just(value); - } - - @Override - public boolean isLeft() { - return false; - } - - @Override - public boolean isRight() { - return true; - } - - @Override - public Either flip() { - return left(value); - } - - @Override - public U collect(Function left, Function right) { - return right.apply(value); - } - } return new Right<>(Objects.requireNonNull(right)); } + record Left(L value) implements Either { + + @Override + @SuppressWarnings("unchecked") + public Either bind(Function>> map) { + return (Either) this; + } + + @Override + public Either mapLeft(Function f) { + return new Left<>(f.apply(value)); + } + + @SuppressWarnings({ "unchecked" }) + @Override + public Either mapRight(Function f) { + return (Either) this; + } + + @Override + public Maybe getLeft() { + return Maybe.just(value); + } + + @Override + public Maybe getRight() { + return Maybe.nothing(); + } + + @Override + public boolean isLeft() { + return true; + } + + @Override + public boolean isRight() { + return false; + } + + @Override + public Either flip() { + return right(value); + } + + @Override + public U collect(Function left, Function right) { + return left.apply(value); + } + } + + + record Right(R value) implements Either { + @Override + public Either bind(Function>> map) { + return (Either) map.apply(value); + } + + @SuppressWarnings({ "unchecked" }) + @Override + public Either mapLeft(Function f) { + return (Either) this; + } + + @Override + public Either mapRight(Function f) { + return new Right<>(f.apply(value)); + } + + @Override + public Maybe getLeft() { + return Maybe.nothing(); + } + + @Override + public Maybe getRight() { + return Maybe.just(value); + } + + @Override + public boolean isLeft() { + return false; + } + + @Override + public boolean isRight() { + return true; + } + + @Override + public Either flip() { + return left(value); + } + + @Override + public U collect(Function left, Function right) { + return right.apply(value); + } + } } \ No newline at end of file diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Maybe.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Maybe.java index cbd981f75..7aa1b683e 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Maybe.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Maybe.java @@ -1,6 +1,7 @@ package com.dfsek.terra.api.util.generic.data.types; import com.dfsek.terra.api.util.generic.control.Monad; +import com.dfsek.terra.api.util.generic.data.LinkedList; import java.util.NoSuchElementException; import java.util.Optional; @@ -11,7 +12,7 @@ import java.util.function.Supplier; import java.util.stream.Stream; -public interface Maybe extends Monad> { +public sealed interface Maybe extends Monad> { @Override default Maybe pure(T1 t) { return just(t); @@ -49,9 +50,20 @@ public interface Maybe extends Monad> { return this; } + default Maybe collapse(Runnable nothing, Consumer just) { + return consume(just).ifNothing(nothing); + } + + + default LinkedList toList() { + return map(LinkedList::of).get(LinkedList::empty); + } /** * Project a new value into this Maybe if it is Nothing. + * Effectively a bind operation over Nothing, treating it as a Void type. + *

+ * Converse of {@link #bind}. */ Maybe or(Supplier> or); @@ -59,7 +71,6 @@ public interface Maybe extends Monad> { return or(() -> just(or.get())); } - @Deprecated default T orThrow() { return get(() -> { throw new NoSuchElementException("No value present."); }); @@ -73,7 +84,6 @@ public interface Maybe extends Monad> { throw e.get(); } - default Maybe or(Maybe or) { return or(() -> or); } @@ -96,85 +106,88 @@ public interface Maybe extends Monad> { } static Maybe just(T1 t) { - record Just(T value) implements Maybe { - @Override - public Optional toOptional() { - return Optional.of(value); - } - - @Override - public Either toEither(L l) { - return Either.right(value); - } - - @Override - public T get(Supplier def) { - return value; - } - - @Override - public boolean isJust() { - return true; - } - - @Override - public Maybe map(Function map) { - return just(map.apply(value)); - } - - @Override - public Maybe or(Supplier> or) { - return this; - } - - @Override - public Maybe bind(Function>> map) { - return (Maybe) map.apply(value); - } - } return new Just<>(t); } static Maybe nothing() { - record Nothing() implements Maybe { - @Override - public Maybe bind(Function>> map) { - return nothing(); - } - - @Override - public Optional toOptional() { - return Optional.empty(); - } - - @Override - public Either toEither(L l) { - return Either.left(l); - } - - @Override - public T get(Supplier def) { - return def.get(); - } - - @Override - public boolean isJust() { - return false; - } - - @Override - @SuppressWarnings("unchecked") - public Maybe map(Function map) { - return (Maybe) this; - } - - @Override - public Maybe or(Supplier> or) { - return or.get(); - } - } return new Nothing<>(); } + + record Just(T value) implements Maybe { + @Override + public Optional toOptional() { + return Optional.of(value); + } + + @Override + public Either toEither(L l) { + return Either.right(value); + } + + @Override + public T get(Supplier def) { + return value; + } + + @Override + public boolean isJust() { + return true; + } + + @Override + public Maybe map(Function map) { + return just(map.apply(value)); + } + + @Override + public Maybe or(Supplier> or) { + return this; + } + + @Override + public Maybe bind(Function>> map) { + return (Maybe) map.apply(value); + } + } + + + record Nothing() implements Maybe { + @Override + public Maybe bind(Function>> map) { + return nothing(); + } + + @Override + public Optional toOptional() { + return Optional.empty(); + } + + @Override + public Either toEither(L l) { + return Either.left(l); + } + + @Override + public T get(Supplier def) { + return def.get(); + } + + @Override + public boolean isJust() { + return false; + } + + @Override + @SuppressWarnings("unchecked") + public Maybe map(Function map) { + return (Maybe) this; + } + + @Override + public Maybe or(Supplier> or) { + return or.get(); + } + } }