com.github.tonivade.purefun.instances.EitherInstances Maven / Gradle / Ivy
/*
* Copyright (c) 2018-2022, Antonio Gabriel Muñoz Conejo
* Distributed under the terms of the MIT License
*/
package com.github.tonivade.purefun.instances;
import static com.github.tonivade.purefun.Function1.cons;
import com.github.tonivade.purefun.Eq;
import com.github.tonivade.purefun.Function1;
import com.github.tonivade.purefun.Function2;
import com.github.tonivade.purefun.Kind;
import com.github.tonivade.purefun.Witness;
import com.github.tonivade.purefun.type.Either;
import com.github.tonivade.purefun.type.EitherOf;
import com.github.tonivade.purefun.type.Either_;
import com.github.tonivade.purefun.type.Eval;
import com.github.tonivade.purefun.type.EvalOf;
import com.github.tonivade.purefun.typeclasses.Applicative;
import com.github.tonivade.purefun.typeclasses.Bifunctor;
import com.github.tonivade.purefun.typeclasses.Foldable;
import com.github.tonivade.purefun.typeclasses.Functor;
import com.github.tonivade.purefun.typeclasses.Monad;
import com.github.tonivade.purefun.typeclasses.MonadError;
import com.github.tonivade.purefun.typeclasses.MonadThrow;
import com.github.tonivade.purefun.typeclasses.Traverse;
@SuppressWarnings("unchecked")
public interface EitherInstances {
static Eq, R>> eq(Eq leftEq, Eq rightEq) {
return (a, b) -> {
if (a instanceof Either.Left leftA && b instanceof Either.Left leftB) {
return leftEq.eqv(leftA.getLeft(), leftB.getLeft());
}
if (a instanceof Either.Right rightA && b instanceof Either.Right rightB) {
return rightEq.eqv(rightA.getRight(), rightB.getRight());
}
return false;
};
}
static Functor> functor() {
return EitherFunctor.INSTANCE;
}
static Bifunctor bifunctor() {
return EitherBifunctor.INSTANCE;
}
static Applicative> applicative() {
return EitherApplicative.INSTANCE;
}
static Monad> monad() {
return EitherMonad.INSTANCE;
}
static MonadError, L> monadError() {
return EitherMonadError.INSTANCE;
}
static MonadThrow> monadThrow() {
return EitherMonadThrow.INSTANCE;
}
static Foldable> foldable() {
return EitherFoldable.INSTANCE;
}
static Traverse> traverse() {
return EitherTraverse.INSTANCE;
}
}
interface EitherFunctor extends Functor> {
@SuppressWarnings("rawtypes")
EitherFunctor INSTANCE = new EitherFunctor() {};
@Override
default Either map(Kind, ? extends T> value, Function1 super T, ? extends R> map) {
return EitherOf.narrowK(value).map(map);
}
}
interface EitherBifunctor extends Bifunctor {
EitherBifunctor INSTANCE = new EitherBifunctor() {};
@Override
default Either bimap(Kind, ? extends B> value,
Function1 super A, ? extends C> leftMap, Function1 super B, ? extends D> rightMap) {
return EitherOf.narrowK(value).bimap(leftMap, rightMap);
}
}
interface EitherPure extends Applicative> {
@Override
default Either pure(T value) {
return Either.right(value);
}
}
interface EitherApplicative extends EitherPure {
@SuppressWarnings("rawtypes")
EitherApplicative INSTANCE = new EitherApplicative() {};
@Override
default Either ap(Kind, ? extends T> value,
Kind, ? extends Function1 super T, ? extends R>> apply) {
return EitherOf.narrowK(value).flatMap(t -> EitherOf.narrowK(apply).map(f -> f.apply(t)));
}
}
interface EitherMonad extends EitherPure, Monad> {
@SuppressWarnings("rawtypes")
EitherMonad INSTANCE = new EitherMonad() {};
@Override
default Either flatMap(Kind, ? extends T> value,
Function1 super T, ? extends Kind, ? extends R>> map) {
return EitherOf.narrowK(value).flatMap(map.andThen(EitherOf::narrowK));
}
}
interface EitherMonadError extends EitherMonad, MonadError, L> {
@SuppressWarnings("rawtypes")
EitherMonadError INSTANCE = new EitherMonadError() {};
@Override
default Either raiseError(L error) {
return Either.left(error);
}
@Override
default Either handleErrorWith(Kind, A> value,
Function1 super L, ? extends Kind, ? extends A>> handler) {
return EitherOf.narrowK(value).fold(handler.andThen(EitherOf::narrowK), Either::right);
}
}
interface EitherMonadThrow extends EitherMonadError, MonadThrow> {
EitherMonadThrow INSTANCE = new EitherMonadThrow() {};
}
interface EitherFoldable extends Foldable> {
@SuppressWarnings("rawtypes")
EitherFoldable INSTANCE = new EitherFoldable() {};
@Override
default B foldLeft(Kind, ? extends A> value, B initial, Function2 super B, ? super A, ? extends B> mapper) {
return EitherOf.narrowK(value).fold(cons(initial), a -> mapper.apply(initial, a));
}
@Override
default Eval foldRight(Kind, ? extends A> value, Eval extends B> initial,
Function2 super A, ? super Eval extends B>, ? extends Eval extends B>> mapper) {
return EitherOf.narrowK(value).fold(
cons(initial).andThen(EvalOf::narrowK),
a -> mapper.andThen(EvalOf::narrowK).apply(a, initial));
}
}
interface EitherTraverse extends Traverse>, EitherFoldable {
@SuppressWarnings("rawtypes")
EitherTraverse INSTANCE = new EitherTraverse() {};
@Override
default Kind, R>> traverse(
Applicative applicative, Kind, T> value,
Function1 super T, ? extends Kind> mapper) {
return EitherOf.narrowK(value).fold(
l -> applicative.pure(Either.left(l).kind()),
t -> {
Kind apply = mapper.apply(t);
return applicative.map(apply, r -> Either.right(r));
});
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy