com.jnape.palatable.lambda.adt.choice.Choice3 Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lambda Show documentation
Show all versions of lambda Show documentation
Functional patterns for Java
package com.jnape.palatable.lambda.adt.choice;
import com.jnape.palatable.lambda.adt.Maybe;
import com.jnape.palatable.lambda.adt.coproduct.CoProduct2;
import com.jnape.palatable.lambda.adt.coproduct.CoProduct3;
import com.jnape.palatable.lambda.adt.hlist.HList;
import com.jnape.palatable.lambda.adt.hlist.Tuple3;
import com.jnape.palatable.lambda.functions.Fn1;
import com.jnape.palatable.lambda.functions.recursion.RecursiveResult;
import com.jnape.palatable.lambda.functions.specialized.Pure;
import com.jnape.palatable.lambda.functor.Applicative;
import com.jnape.palatable.lambda.functor.Bifunctor;
import com.jnape.palatable.lambda.functor.Functor;
import com.jnape.palatable.lambda.functor.builtin.Lazy;
import com.jnape.palatable.lambda.monad.Monad;
import com.jnape.palatable.lambda.monad.MonadRec;
import com.jnape.palatable.lambda.traversable.Traversable;
import java.util.Objects;
import static com.jnape.palatable.lambda.functions.builtin.fn2.Into3.into3;
import static com.jnape.palatable.lambda.functions.recursion.RecursiveResult.terminate;
import static com.jnape.palatable.lambda.functions.recursion.Trampoline.trampoline;
import static com.jnape.palatable.lambda.functor.builtin.Lazy.lazy;
/**
* Canonical ADT representation of {@link CoProduct3}.
*
* @param the first possible type
* @param the second possible type
* @param the third possible type
* @see Choice2
* @see Choice4
*/
public abstract class Choice3 implements
CoProduct3>,
MonadRec>,
Bifunctor>,
Traversable> {
private Choice3() {
}
/**
* Specialize this choice's projection to a {@link Tuple3}.
*
* @return a {@link Tuple3}
*/
@Override
public Tuple3, Maybe, Maybe> project() {
return into3(HList::tuple, CoProduct3.super.project());
}
/**
* {@inheritDoc}
*/
@Override
public final Choice4 diverge() {
return match(Choice4::a, Choice4::b, Choice4::c);
}
/**
* {@inheritDoc}
*/
@Override
public final Choice2 converge(Fn1 super C, ? extends CoProduct2> convergenceFn) {
return match(Choice2::a, Choice2::b, convergenceFn.fmap(cp2 -> cp2.match(Choice2::a, Choice2::b)));
}
/**
* {@inheritDoc}
*/
@Override
public final Choice3 fmap(Fn1 super C, ? extends D> fn) {
return MonadRec.super.fmap(fn).coerce();
}
/**
* {@inheritDoc}
*/
@Override
public final Choice3 biMapL(Fn1 super B, ? extends D> fn) {
return (Choice3) Bifunctor.super.biMapL(fn);
}
/**
* {@inheritDoc}
*/
@Override
public final Choice3 biMapR(Fn1 super C, ? extends D> fn) {
return (Choice3) Bifunctor.super.biMapR(fn);
}
/**
* {@inheritDoc}
*/
@Override
public final Choice3 biMap(Fn1 super B, ? extends D> lFn,
Fn1 super C, ? extends E> rFn) {
return match(Choice3::a, b -> b(lFn.apply(b)), c -> c(rFn.apply(c)));
}
/**
* {@inheritDoc}
*/
@Override
public Choice3 pure(D d) {
return c(d);
}
/**
* {@inheritDoc}
*/
@Override
public Choice3 zip(Applicative, Choice3> appFn) {
return MonadRec.super.zip(appFn).coerce();
}
/**
* {@inheritDoc}
*/
@Override
public Lazy> lazyZip(
Lazy extends Applicative, Choice3>> lazyAppFn) {
return match(a -> lazy(a(a)),
b -> lazy(b(b)),
c -> lazyAppFn.fmap(choiceF -> choiceF.fmap(f -> f.apply(c)).coerce()));
}
/**
* {@inheritDoc}
*/
@Override
public Choice3 discardL(Applicative> appB) {
return MonadRec.super.discardL(appB).coerce();
}
/**
* {@inheritDoc}
*/
@Override
public Choice3 discardR(Applicative> appB) {
return MonadRec.super.discardR(appB).coerce();
}
/**
* {@inheritDoc}
*/
@Override
public Choice3 flatMap(Fn1 super C, ? extends Monad>> f) {
return match(Choice3::a, Choice3::b, c -> f.apply(c).coerce());
}
/**
* {@inheritDoc}
*/
@Override
public Choice3 trampolineM(
Fn1 super C, ? extends MonadRec, Choice3>> fn) {
return flatMap(trampoline(c -> fn.apply(c).>>coerce()
.match(a -> terminate(a(a)),
b -> terminate(b(b)),
r -> r.fmap(Choice3::c))));
}
/**
* {@inheritDoc}
*/
@Override
public , TravB extends Traversable>,
AppTrav extends Applicative> AppTrav traverse(Fn1 super C, ? extends Applicative> fn,
Fn1 super TravB, ? extends AppTrav> pure) {
return match(a -> pure.apply(Choice3.a(a).coerce()),
b -> pure.apply(Choice3.b(b).coerce()),
c -> fn.apply(c).>fmap(Choice3::c).fmap(Functor::coerce))
.coerce();
}
/**
* Static factory method for wrapping a value of type A
in a {@link Choice3}.
*
* @param a the value
* @param the first possible type
* @param the second possible type
* @param the third possible type
* @return the wrapped value as a {@link Choice3}<A, B, C>
*/
public static Choice3 a(A a) {
return new _A<>(a);
}
/**
* Static factory method for wrapping a value of type A
in a {@link Choice3}.
*
* @param b the value
* @param the first possible type
* @param the second possible type
* @param the third possible type
* @return the wrapped value as a {@link Choice3}<A, B, C>
*/
public static Choice3 b(B b) {
return new _B<>(b);
}
/**
* Static factory method for wrapping a value of type A
in a {@link Choice3}.
*
* @param c the value
* @param the first possible type
* @param the second possible type
* @param the third possible type
* @return the wrapped value as a {@link Choice3}<A, B, C>
*/
public static Choice3 c(C c) {
return new _C<>(c);
}
/**
* The canonical {@link Pure} instance for {@link Choice3}.
*
* @param the first possible type
* @param the second possible type
* @return the {@link Pure} instance
*/
public static Pure> pureChoice() {
return Choice3::c;
}
private static final class _A extends Choice3 {
private final A a;
private _A(A a) {
this.a = a;
}
@Override
public R match(Fn1 super A, ? extends R> aFn, Fn1 super B, ? extends R> bFn,
Fn1 super C, ? extends R> cFn) {
return aFn.apply(a);
}
@Override
public boolean equals(Object other) {
return other instanceof _A
&& Objects.equals(a, ((_A) other).a);
}
@Override
public int hashCode() {
return Objects.hash(a);
}
@Override
public String toString() {
return "Choice3{" +
"a=" + a +
'}';
}
}
private static final class _B extends Choice3 {
private final B b;
private _B(B b) {
this.b = b;
}
@Override
public R match(Fn1 super A, ? extends R> aFn, Fn1 super B, ? extends R> bFn,
Fn1 super C, ? extends R> cFn) {
return bFn.apply(b);
}
@Override
public boolean equals(Object other) {
return other instanceof _B
&& Objects.equals(b, ((_B) other).b);
}
@Override
public int hashCode() {
return Objects.hash(b);
}
@Override
public String toString() {
return "Choice3{" +
"b=" + b +
'}';
}
}
private static final class _C extends Choice3 {
private final C c;
private _C(C c) {
this.c = c;
}
@Override
public R match(Fn1 super A, ? extends R> aFn, Fn1 super B, ? extends R> bFn,
Fn1 super C, ? extends R> cFn) {
return cFn.apply(c);
}
@Override
public boolean equals(Object other) {
return other instanceof _C
&& Objects.equals(c, ((_C) other).c);
}
@Override
public int hashCode() {
return Objects.hash(c);
}
@Override
public String toString() {
return "Choice3{" +
"c=" + c +
'}';
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy