Groowt-all and fp.

This commit is contained in:
JesseBrault0709 2024-05-13 14:14:21 +02:00
commit 8955630a2f
11 changed files with 507 additions and 0 deletions

26
build.gradle Normal file
View 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
}
}
}

View 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;
}
}
}

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

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

View 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;
}
}

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

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

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

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

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

View 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;
}
}