Groowt-all and fp.
This commit is contained in:
commit
8955630a2f
26
build.gradle
Normal file
26
build.gradle
Normal file
@ -0,0 +1,26 @@
|
||||
plugins {
|
||||
id 'groowt-conventions'
|
||||
id 'groowt-publish'
|
||||
id 'java-library'
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnlyApi libs.jetbrains.anotations
|
||||
}
|
||||
|
||||
jar {
|
||||
archiveBaseName = 'groowt-util-fp'
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
create('fp', MavenPublication) {
|
||||
artifactId = 'groowt-util-fp'
|
||||
from components.java
|
||||
}
|
||||
}
|
||||
}
|
90
src/main/java/groowt/util/fp/either/Either.java
Normal file
90
src/main/java/groowt/util/fp/either/Either.java
Normal file
@ -0,0 +1,90 @@
|
||||
package groowt.util.fp.either;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public sealed interface Either<E, T> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <E, T> Either<E, T> left(E error) {
|
||||
return (Either<E, T>) new Left<>(error);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <E, T> Either<E, T> right(T item) {
|
||||
return (Either<E, T>) new Right<>(item);
|
||||
}
|
||||
|
||||
final class Left<E> implements Either<E, Object> {
|
||||
|
||||
private final E error;
|
||||
|
||||
public Left(E error) {
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public E get() {
|
||||
return this.error;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
final class Right<T> implements Either<Object, T> {
|
||||
|
||||
private final T item;
|
||||
|
||||
public Right(T item) {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
public T get() {
|
||||
return this.item;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
default boolean isLeft() {
|
||||
return this instanceof Either.Left;
|
||||
}
|
||||
|
||||
default boolean isRight() {
|
||||
return this instanceof Either.Right;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
default Left<E> asLeft() {
|
||||
return (Left<E>) this;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
default Right<T> asRight() {
|
||||
return (Right<T>) this;
|
||||
}
|
||||
|
||||
default E getLeft() {
|
||||
return this.asLeft().get();
|
||||
}
|
||||
|
||||
default T getRight() {
|
||||
return this.asRight().get();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
default Either<E, T> mapLeft(Function<? super E, ? extends T> onLeft) {
|
||||
if (this.isLeft()) {
|
||||
return (Either<E, T>) new Right<>(onLeft.apply(this.getLeft()));
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
default Either<E, T> flatMapLeft(Function<? super E, Either<E, ? extends T>> onLeft) {
|
||||
if (this.isLeft()) {
|
||||
final var error = this.getLeft();
|
||||
return (Either<E, T>) onLeft.apply(error);
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
23
src/main/java/groowt/util/fp/hkt/Monoid.java
Normal file
23
src/main/java/groowt/util/fp/hkt/Monoid.java
Normal file
@ -0,0 +1,23 @@
|
||||
package groowt.util.fp.hkt;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public final class Monoid<T> {
|
||||
|
||||
private final SemiGroup<T> semiGroup;
|
||||
private final Zero<T> zero;
|
||||
|
||||
public Monoid(SemiGroup<T> semiGroup, Zero<T> zero) {
|
||||
this.semiGroup = Objects.requireNonNull(semiGroup);
|
||||
this.zero = Objects.requireNonNull(zero);
|
||||
}
|
||||
|
||||
public T concat(T left, T right) {
|
||||
return this.semiGroup.concat(left, right);
|
||||
}
|
||||
|
||||
public T empty() {
|
||||
return this.zero.getEmpty();
|
||||
}
|
||||
|
||||
}
|
17
src/main/java/groowt/util/fp/hkt/SemiGroup.java
Normal file
17
src/main/java/groowt/util/fp/hkt/SemiGroup.java
Normal file
@ -0,0 +1,17 @@
|
||||
package groowt.util.fp.hkt;
|
||||
|
||||
import java.util.function.BinaryOperator;
|
||||
|
||||
public final class SemiGroup<T> {
|
||||
|
||||
private final BinaryOperator<T> concat;
|
||||
|
||||
public SemiGroup(BinaryOperator<T> concat) {
|
||||
this.concat = concat;
|
||||
}
|
||||
|
||||
public T concat(T left, T right) {
|
||||
return this.concat.apply(left, right);
|
||||
}
|
||||
|
||||
}
|
17
src/main/java/groowt/util/fp/hkt/Zero.java
Normal file
17
src/main/java/groowt/util/fp/hkt/Zero.java
Normal file
@ -0,0 +1,17 @@
|
||||
package groowt.util.fp.hkt;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public final class Zero<T> {
|
||||
|
||||
private final T empty;
|
||||
|
||||
public Zero(T empty) {
|
||||
this.empty = Objects.requireNonNull(empty);
|
||||
}
|
||||
|
||||
public T getEmpty() {
|
||||
return this.empty;
|
||||
}
|
||||
|
||||
}
|
159
src/main/java/groowt/util/fp/option/Option.java
Normal file
159
src/main/java/groowt/util/fp/option/Option.java
Normal file
@ -0,0 +1,159 @@
|
||||
package groowt.util.fp.option;
|
||||
|
||||
import groowt.util.fp.hkt.Monoid;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public abstract sealed class Option<T> {
|
||||
|
||||
private static EmptyOption<Object> emptyInstance;
|
||||
|
||||
public static <T> Option<T> lift(T value) {
|
||||
return new ValueOption<>(Objects.requireNonNull(value));
|
||||
}
|
||||
|
||||
public static <T> Option<T> liftNullable(@Nullable T value) {
|
||||
return value == null ? empty() : lift(value);
|
||||
}
|
||||
|
||||
public static <T> Option<T> liftLazy(Supplier<? extends @NotNull T> valueSupplier) {
|
||||
return new SupplierOption<>(Objects.requireNonNull(valueSupplier));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> Option<T> empty() {
|
||||
if (emptyInstance == null) {
|
||||
emptyInstance = new EmptyOption<>();
|
||||
}
|
||||
return (Option<T>) emptyInstance;
|
||||
}
|
||||
|
||||
private static final class EmptyOption<T> extends Option<T> {
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
throw new NullPointerException("Cannot get() on EmptyOption");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPresent() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final class ValueOption<T> extends Option<T> {
|
||||
|
||||
private final T value;
|
||||
|
||||
public ValueOption(T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final class SupplierOption<T> extends Option<T> {
|
||||
|
||||
private final Supplier<T> valueSupplier;
|
||||
|
||||
public SupplierOption(Supplier<? extends T> valueSupplier) {
|
||||
this.valueSupplier = valueSupplier::get;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
return Objects.requireNonNull(
|
||||
this.valueSupplier.get(),
|
||||
"Cannot get() when the given valueSupplier returns null."
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public abstract T get();
|
||||
|
||||
public boolean isPresent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public @NotNull T getOrElse(T other) {
|
||||
return this.isPresent() ? this.get() : Objects.requireNonNull(other);
|
||||
}
|
||||
|
||||
public @Nullable T getOrElseNull() {
|
||||
return this.isPresent() ? this.get() : null;
|
||||
}
|
||||
|
||||
public Option<T> orElseLift(T other) {
|
||||
return this.isPresent() ? this : new ValueOption<>(Objects.requireNonNull(other));
|
||||
}
|
||||
|
||||
public Option<T> orElseLiftLazy(Supplier<? extends @NotNull T> lazyOther) {
|
||||
return this.isPresent() ? this : new SupplierOption<>(Objects.requireNonNull(lazyOther));
|
||||
}
|
||||
|
||||
public <U> Option<U> map(Function<? super T, ? extends @NotNull U> mapper) {
|
||||
return new SupplierOption<>(() -> mapper.apply(this.get()));
|
||||
}
|
||||
|
||||
public <U> Option<U> mapLazy(Function<? super T, ? extends Supplier<? extends @NotNull U>> lazyMapper) {
|
||||
return new SupplierOption<>(() -> lazyMapper.apply(this.get()).get());
|
||||
}
|
||||
|
||||
public <U> Option<U> flatMap(Function<? super T, Option<? extends U>> mapper) {
|
||||
return new SupplierOption<>(() -> mapper.apply(this.get()).get());
|
||||
}
|
||||
|
||||
public <U> Option<U> flatMapLazy(Function<? super T, Option<Supplier<? extends @NotNull U>>> lazyMapper) {
|
||||
return new SupplierOption<>(() -> lazyMapper.apply(this.get()).get().get());
|
||||
}
|
||||
|
||||
public void ifPresent(Consumer<T> onPresent) {
|
||||
if (this.isPresent()) {
|
||||
onPresent.accept(this.get());
|
||||
}
|
||||
}
|
||||
|
||||
public void ifPresentOrElse(Consumer<T> onPresent, Runnable orElse) {
|
||||
if (this.isPresent()) {
|
||||
onPresent.accept(this.get());
|
||||
} else {
|
||||
orElse.run();
|
||||
}
|
||||
}
|
||||
|
||||
public <R> R fold(Function<? super T, ? extends R> onPresent, Supplier<? extends R> onEmpty) {
|
||||
if (this.isPresent()) {
|
||||
return onPresent.apply(this.get());
|
||||
} else {
|
||||
return onEmpty.get();
|
||||
}
|
||||
}
|
||||
|
||||
public <R> R foldMap(Monoid<R> monoid, Function<? super T, ? extends R> onPresent) {
|
||||
if (this.isPresent()) {
|
||||
return onPresent.apply(this.get());
|
||||
} else {
|
||||
return monoid.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public <R> R foldFlatMap(Monoid<R> monoid, Function<? super T, Option<? extends R>> onPresent) {
|
||||
if (this.isPresent()) {
|
||||
return onPresent.apply(this.get()).get();
|
||||
} else {
|
||||
return monoid.empty();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
56
src/main/java/groowt/util/fp/property/Property.java
Normal file
56
src/main/java/groowt/util/fp/property/Property.java
Normal file
@ -0,0 +1,56 @@
|
||||
package groowt.util.fp.property;
|
||||
|
||||
import groowt.util.fp.provider.Provider;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface Property<T> extends Provider<T> {
|
||||
|
||||
static <T> Property<T> get(Class<? extends T> tClass) {
|
||||
return new SimpleProperty<>();
|
||||
}
|
||||
|
||||
static <T> Property<T> of(T t) {
|
||||
final Property<T> property = new SimpleProperty<>();
|
||||
property.set(t);
|
||||
return property;
|
||||
}
|
||||
|
||||
static <T> Property<T> ofLazy(Provider<T> tProvider) {
|
||||
final Property<T> property = new SimpleProperty<>();
|
||||
property.set(tProvider);
|
||||
return property;
|
||||
}
|
||||
|
||||
static <T> Property<T> ofLazy(Supplier<T> tSupplier) {
|
||||
final Property<T> property = new SimpleProperty<>();
|
||||
property.set(Provider.ofLazy(tSupplier));
|
||||
return property;
|
||||
}
|
||||
|
||||
void set(T t);
|
||||
void set(Provider<? extends T> tProvider);
|
||||
void setConvention(T t);
|
||||
void setConvention(Provider<? extends T> tProvider);
|
||||
|
||||
boolean isPresent();
|
||||
boolean isEmpty();
|
||||
|
||||
default T fold(@Nullable T onEmpty) {
|
||||
if (this.isPresent()) {
|
||||
return this.get();
|
||||
} else {
|
||||
return onEmpty;
|
||||
}
|
||||
}
|
||||
|
||||
default T fold(Provider<? extends T> onEmpty) {
|
||||
if (this.isPresent()) {
|
||||
return this.get();
|
||||
} else {
|
||||
return onEmpty.get();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
57
src/main/java/groowt/util/fp/property/SimpleProperty.java
Normal file
57
src/main/java/groowt/util/fp/property/SimpleProperty.java
Normal file
@ -0,0 +1,57 @@
|
||||
package groowt.util.fp.property;
|
||||
|
||||
import groowt.util.fp.provider.Provider;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
final class SimpleProperty<T> implements Property<T> {
|
||||
|
||||
private Provider<? extends T> provider;
|
||||
private Provider<? extends T> convention;
|
||||
|
||||
@Override
|
||||
public boolean isPresent() {
|
||||
return this.provider != null || this.convention != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return this.provider == null && this.convention == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(T t) {
|
||||
Objects.requireNonNull(t);
|
||||
this.provider = Provider.of(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(Provider<? extends T> tProvider) {
|
||||
Objects.requireNonNull(tProvider);
|
||||
this.provider = tProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConvention(T convention) {
|
||||
Objects.requireNonNull(convention);
|
||||
this.convention = Provider.of(convention);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConvention(Provider<? extends T> convention) {
|
||||
Objects.requireNonNull(convention);
|
||||
this.convention = convention;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
if (!this.isPresent()) {
|
||||
throw new NullPointerException("Cannot get() from an empty Property. Set the value or set the convention.");
|
||||
} else if (this.provider != null) {
|
||||
return this.provider.get();
|
||||
} else {
|
||||
return this.convention.get();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
18
src/main/java/groowt/util/fp/provider/LazyProvider.java
Normal file
18
src/main/java/groowt/util/fp/provider/LazyProvider.java
Normal file
@ -0,0 +1,18 @@
|
||||
package groowt.util.fp.provider;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
final class LazyProvider<T> implements Provider<T> {
|
||||
|
||||
private final Supplier<? extends T> lazy;
|
||||
|
||||
public LazyProvider(Supplier<? extends T> supplier) {
|
||||
this.lazy = supplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
return this.lazy.get();
|
||||
}
|
||||
|
||||
}
|
26
src/main/java/groowt/util/fp/provider/Provider.java
Normal file
26
src/main/java/groowt/util/fp/provider/Provider.java
Normal file
@ -0,0 +1,26 @@
|
||||
package groowt.util.fp.provider;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface Provider<T> {
|
||||
|
||||
static <T> Provider<T> of(T t) {
|
||||
return new SimpleProvider<>(t);
|
||||
}
|
||||
|
||||
static <T> Provider<T> ofLazy(Supplier<? extends T> tSupplier) {
|
||||
return new LazyProvider<>(tSupplier);
|
||||
}
|
||||
|
||||
T get();
|
||||
|
||||
default <U> Provider<U> map(Function<? super T, ? extends U> mapper) {
|
||||
return new LazyProvider<>(() -> mapper.apply(this.get()));
|
||||
}
|
||||
|
||||
default <U> Provider<U> flatMap(Function<? super T, ? extends Provider<? extends U>> flatMapper) {
|
||||
return new LazyProvider<>(() -> flatMapper.apply(this.get()).get());
|
||||
}
|
||||
|
||||
}
|
18
src/main/java/groowt/util/fp/provider/SimpleProvider.java
Normal file
18
src/main/java/groowt/util/fp/provider/SimpleProvider.java
Normal file
@ -0,0 +1,18 @@
|
||||
package groowt.util.fp.provider;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
final class SimpleProvider<T> implements Provider<T> {
|
||||
|
||||
private final T t;
|
||||
|
||||
public SimpleProvider(T t) {
|
||||
this.t = Objects.requireNonNull(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
return t;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user