Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java 17 #129

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 7 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -672,24 +672,15 @@ There are three functions that lambda provides that interface directly with lens
Lenses can be easily created. Consider the following `Person` class:

```Java
public final class Person {
private final int age;
public record Person(int age) {

public Person(int age) {
this.age = age;
}

public int getAge() {
return age;
}
public Person setAge(int age) {
return new Person(age);
}

public Person setAge(int age) {
return new Person(age);
}

public Person setAge(LocalDate dob) {
return setAge((int) YEARS.between(dob, LocalDate.now()));
}
public Person setAge(LocalDate dob) {
return setAge((int) YEARS.between(dob, LocalDate.now()));
}
}
```

Expand Down
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<source>17</source>
<target>17</target>
<compilerArgs>
<compilerArg>-Xlint:all</compilerArg>
<compilerArg>-Werror</compilerArg>
Expand Down
116 changes: 41 additions & 75 deletions src/main/java/com/jnape/palatable/lambda/adt/Maybe.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import com.jnape.palatable.lambda.monad.MonadRec;
import com.jnape.palatable.lambda.traversable.Traversable;

import java.util.Objects;
import java.util.Optional;

import static com.jnape.palatable.lambda.adt.Either.left;
Expand All @@ -38,22 +37,20 @@
* @param <A> the optional parameter type
* @see Optional
*/
public abstract class Maybe<A> implements
public sealed interface Maybe<A> extends
CoProduct2<Unit, A, Maybe<A>>,
MonadError<Unit, A, Maybe<?>>,
MonadRec<A, Maybe<?>>,
Traversable<A, Maybe<?>> {
Traversable<A, Maybe<?>> permits Just, Nothing {

private Maybe() {
}

/**
* If the value is present, return it; otherwise, return the value supplied by <code>otherSupplier</code>.
*
* @param otherFn0 the supplier for the other value
* @return this value, or the supplied other value
*/
public final A orElseGet(Fn0<A> otherFn0) {
default A orElseGet(Fn0<A> otherFn0) {
return match(__ -> otherFn0.apply(), id());
}

Expand All @@ -63,7 +60,7 @@ public final A orElseGet(Fn0<A> otherFn0) {
* @param other the other value
* @return this value, or the other value
*/
public final A orElse(A other) {
default A orElse(A other) {
return orElseGet(() -> other);
}

Expand All @@ -76,7 +73,7 @@ public final A orElse(A other) {
* @return the value, if present
* @throws E the throwable, if the value is absent
*/
public final <E extends Throwable> A orElseThrow(Fn0<? extends E> throwableSupplier) throws E {
default <E extends Throwable> A orElseThrow(Fn0<? extends E> throwableSupplier) throws E {
return orElseGet(fn0(() -> {
throw throwableSupplier.apply();
}));
Expand All @@ -89,23 +86,23 @@ public final <E extends Throwable> A orElseThrow(Fn0<? extends E> throwableSuppl
* @param predicate the predicate to apply to the possibly absent value
* @return maybe the present value that satisfied the predicate
*/
public final Maybe<A> filter(Fn1<? super A, ? extends Boolean> predicate) {
default Maybe<A> filter(Fn1<? super A, ? extends Boolean> predicate) {
return flatMap(a -> predicate.apply(a) ? just(a) : nothing());
}

/**
* {@inheritDoc}
*/
@Override
public Maybe<A> throwError(Unit unit) {
default Maybe<A> throwError(Unit unit) {
return nothing();
}

/**
* {@inheritDoc}
*/
@Override
public Maybe<A> catchError(Fn1<? super Unit, ? extends Monad<A, Maybe<?>>> recoveryFn) {
default Maybe<A> catchError(Fn1<? super Unit, ? extends Monad<A, Maybe<?>>> recoveryFn) {
return match(recoveryFn, Maybe::just).coerce();
}

Expand All @@ -117,7 +114,7 @@ public Maybe<A> catchError(Fn1<? super Unit, ? extends Monad<A, Maybe<?>>> recov
* @param lFn0 the supplier for the left value
* @return this value wrapped in an Either.right, or an Either.left around the result of lSupplier
*/
public final <L> Either<L, A> toEither(Fn0<L> lFn0) {
default <L> Either<L, A> toEither(Fn0<L> lFn0) {
return fmap(Either::<L, A>right).orElseGet(() -> left(lFn0.apply()));
}

Expand All @@ -126,7 +123,7 @@ public final <L> Either<L, A> toEither(Fn0<L> lFn0) {
*
* @return the Optional
*/
public final Optional<A> toOptional() {
default Optional<A> toOptional() {
return fmap(Optional::of).orElseGet(Optional::empty);
}

Expand All @@ -138,7 +135,7 @@ public final Optional<A> toOptional() {
* @return Just b
*/
@Override
public final <B> Maybe<B> pure(B b) {
default <B> Maybe<B> pure(B b) {
return just(b);
}

Expand All @@ -149,15 +146,15 @@ public final <B> Maybe<B> pure(B b) {
* {@link Maybe#nothing}.
*/
@Override
public final <B> Maybe<B> fmap(Fn1<? super A, ? extends B> fn) {
default <B> Maybe<B> fmap(Fn1<? super A, ? extends B> fn) {
return MonadError.super.<B>fmap(fn).coerce();
}

/**
* {@inheritDoc}
*/
@Override
public final <B> Maybe<B> zip(Applicative<Fn1<? super A, ? extends B>, Maybe<?>> appFn) {
default <B> Maybe<B> zip(Applicative<Fn1<? super A, ? extends B>, Maybe<?>> appFn) {
return MonadError.super.zip(appFn).coerce();
}

Expand All @@ -169,7 +166,7 @@ public final <B> Maybe<B> zip(Applicative<Fn1<? super A, ? extends B>, Maybe<?>>
* @return the zipped {@link Maybe}
*/
@Override
public <B> Lazy<Maybe<B>> lazyZip(Lazy<? extends Applicative<Fn1<? super A, ? extends B>, Maybe<?>>> lazyAppFn) {
default <B> Lazy<Maybe<B>> lazyZip(Lazy<? extends Applicative<Fn1<? super A, ? extends B>, Maybe<?>>> lazyAppFn) {
return match(constantly(lazy(nothing())),
a -> lazyAppFn.fmap(maybeF -> maybeF.<B>fmap(f -> f.apply(a)).coerce()));
}
Expand All @@ -178,15 +175,15 @@ public <B> Lazy<Maybe<B>> lazyZip(Lazy<? extends Applicative<Fn1<? super A, ? ex
* {@inheritDoc}
*/
@Override
public final <B> Maybe<B> discardL(Applicative<B, Maybe<?>> appB) {
default <B> Maybe<B> discardL(Applicative<B, Maybe<?>> appB) {
return MonadError.super.discardL(appB).coerce();
}

/**
* {@inheritDoc}
*/
@Override
public final <B> Maybe<A> discardR(Applicative<B, Maybe<?>> appB) {
default <B> Maybe<A> discardR(Applicative<B, Maybe<?>> appB) {
return MonadError.super.discardR(appB).coerce();
}

Expand All @@ -195,15 +192,15 @@ public final <B> Maybe<A> discardR(Applicative<B, Maybe<?>> appB) {
*/
@SuppressWarnings("RedundantTypeArguments")
@Override
public final <B> Maybe<B> flatMap(Fn1<? super A, ? extends Monad<B, Maybe<?>>> f) {
default <B> Maybe<B> flatMap(Fn1<? super A, ? extends Monad<B, Maybe<?>>> f) {
return match(constantly(nothing()), f.fmap(Monad<B, Maybe<?>>::coerce));
}

/**
* {@inheritDoc}
*/
@Override
public <B> Maybe<B> trampolineM(Fn1<? super A, ? extends MonadRec<RecursiveResult<A, B>, Maybe<?>>> fn) {
default <B> Maybe<B> trampolineM(Fn1<? super A, ? extends MonadRec<RecursiveResult<A, B>, Maybe<?>>> fn) {
return match(constantly(nothing()), trampoline(a -> fn.apply(a).<Maybe<RecursiveResult<A, B>>>coerce()
.match(constantly(terminate(nothing())),
aOrB -> aOrB.fmap(Maybe::just))));
Expand All @@ -213,23 +210,23 @@ public <B> Maybe<B> trampolineM(Fn1<? super A, ? extends MonadRec<RecursiveResul
* {@inheritDoc}
*/
@Override
public <B> Choice3<Unit, A, B> diverge() {
default <B> Choice3<Unit, A, B> diverge() {
return match(Choice3::a, Choice3::b);
}

/**
* {@inheritDoc}
*/
@Override
public Tuple2<Maybe<Unit>, Maybe<A>> project() {
default Tuple2<Maybe<Unit>, Maybe<A>> project() {
return CoProduct2.super.project().into(HList::tuple);
}

/**
* {@inheritDoc}
*/
@Override
public Choice2<A, Unit> invert() {
default Choice2<A, Unit> invert() {
return match(Choice2::b, Choice2::a);
}

Expand All @@ -241,13 +238,13 @@ public Choice2<A, Unit> invert() {
* @deprecated in favor of {@link Maybe#match(Fn1, Fn1) matching} into an {@link IO} and explicitly running it
*/
@Deprecated
public final Maybe<A> peek(Fn1<? super A, ? extends IO<?>> effect) {
default Maybe<A> peek(Fn1<? super A, ? extends IO<?>> effect) {
return match(constantly(io(this)), a -> effect.apply(a).fmap(constantly(this))).unsafePerformIO();
}

@Override
@SuppressWarnings("unchecked")
public final <B, App extends Applicative<?, App>, TravB extends Traversable<B, Maybe<?>>,
default <B, App extends Applicative<?, App>, TravB extends Traversable<B, Maybe<?>>,
AppTrav extends Applicative<TravB, App>> AppTrav traverse(Fn1<? super A, ? extends Applicative<B, App>> fn,
Fn1<? super TravB, ? extends AppTrav> pure) {
return match(__ -> pure.apply((TravB) Maybe.<B>nothing()), a -> (AppTrav) fn.apply(a).fmap(Maybe::just));
Expand All @@ -261,7 +258,7 @@ AppTrav extends Applicative<TravB, App>> AppTrav traverse(Fn1<? super A, ? exten
* @param <A> the potential right value
* @return "Just" the right value, or nothing
*/
public static <A> Maybe<A> fromEither(Either<?, A> either) {
static <A> Maybe<A> fromEither(Either<?, A> either) {
return either.toMaybe();
}

Expand All @@ -272,7 +269,7 @@ public static <A> Maybe<A> fromEither(Either<?, A> either) {
* @param <A> the optional parameter type
* @return the equivalent Maybe instance
*/
public static <A> Maybe<A> fromOptional(Optional<? extends A> optional) {
static <A> Maybe<A> fromOptional(Optional<? extends A> optional) {
return optional.map(Maybe::<A>just).orElse(Maybe.nothing());
}

Expand All @@ -284,7 +281,7 @@ public static <A> Maybe<A> fromOptional(Optional<? extends A> optional) {
* @param <A> the value parameter type
* @return "Just" the value, or nothing
*/
public static <A> Maybe<A> maybe(A a) {
static <A> Maybe<A> maybe(A a) {
return a == null ? nothing() : just(a);
}

Expand All @@ -297,7 +294,7 @@ public static <A> Maybe<A> maybe(A a) {
* @return "Just" the value
* @throws NullPointerException if a is null
*/
public static <A> Maybe<A> just(A a) {
static <A> Maybe<A> just(A a) {
if (a == null)
throw new NullPointerException();
return new Just<>(a);
Expand All @@ -310,7 +307,7 @@ public static <A> Maybe<A> just(A a) {
* @return nothing
*/
@SuppressWarnings("unchecked")
public static <A> Maybe<A> nothing() {
static <A> Maybe<A> nothing() {
return (Maybe<A>) Nothing.INSTANCE;
}

Expand All @@ -319,53 +316,22 @@ public static <A> Maybe<A> nothing() {
*
* @return the {@link Pure} instance
*/
public static Pure<Maybe<?>> pureMaybe() {
static Pure<Maybe<?>> pureMaybe() {
return Maybe::just;
}
}
record Nothing<A>() implements Maybe<A> {
static final Nothing<?> INSTANCE = new Nothing<>();

private static final class Nothing<A> extends Maybe<A> {
private static final Nothing<?> INSTANCE = new Nothing<>();

private Nothing() {
}

@Override
public <R> R match(Fn1<? super Unit, ? extends R> aFn, Fn1<? super A, ? extends R> bFn) {
return aFn.apply(UNIT);
}

@Override
public String toString() {
return "Nothing";
}
@Override
public <R> R match(Fn1<? super Unit, ? extends R> aFn, Fn1<? super A, ? extends R> bFn) {
return aFn.apply(UNIT);
}
}

private static final class Just<A> extends Maybe<A> {

private final A a;

private Just(A a) {
this.a = a;
}

@Override
public <R> R match(Fn1<? super Unit, ? extends R> aFn, Fn1<? super A, ? extends R> bFn) {
return bFn.apply(a);
}

@Override
public boolean equals(Object other) {
return other instanceof Just && Objects.equals(this.a, ((Just) other).a);
}

@Override
public int hashCode() {
return Objects.hash(a);
}

@Override
public String toString() {
return "Just " + a;
}
record Just<A>(A a) implements Maybe<A> {
@Override
public <R> R match(Fn1<? super Unit, ? extends R> aFn, Fn1<? super A, ? extends R> bFn) {
return bFn.apply(a);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,7 @@ public Tail tail() {

@Override
public final boolean equals(Object other) {
if (other instanceof HCons) {
HCons<?, ?> that = (HCons<?, ?>) other;
if (other instanceof HCons<?, ?> that) {
return this.head.equals(that.head)
&& this.tail.equals(that.tail);
}
Expand Down
3 changes: 1 addition & 2 deletions src/main/java/com/jnape/palatable/lambda/adt/hmap/HMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,7 @@ public Collection<Object> values() {

@Override
public boolean equals(Object other) {
if (other instanceof HMap) {
HMap that = (HMap) other;
if (other instanceof HMap that) {
return Objects.equals(this.table, that.table);
}
return false;
Expand Down