com.github.tonivade.purefun.instances.EitherInstances Maven / Gradle / Ivy
/*
* Copyright (c) 2018-2020, 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.Pattern2;
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.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) -> Pattern2., Either, Boolean>build()
.when((x, y) -> x.isLeft() && y.isLeft())
.then((x, y) -> leftEq.eqv(x.getLeft(), y.getLeft()))
.when((x, y) -> x.isRight() && y.isRight())
.then((x, y) -> rightEq.eqv(x.getRight(), y.getRight()))
.otherwise()
.returns(false)
.apply(EitherOf.narrowK(a), EitherOf.narrowK(b));
}
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, T> value, Function1 map) {
return EitherOf.narrowK(value).map(map);
}
}
interface EitherBifunctor extends Bifunctor {
EitherBifunctor INSTANCE = new EitherBifunctor() {};
@Override
default Either bimap(Kind, B> value,
Function1 leftMap, Function1 rightMap) {
return EitherOf.narrowK(value).mapLeft(leftMap).map(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, T> value,
Kind, Function1> 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, T> value,
Function1, 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, 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, A> value, B initial, Function2 mapper) {
return EitherOf.narrowK(value).fold(cons(initial), a -> mapper.apply(initial, a));
}
@Override
default Eval foldRight(Kind, A> value, Eval initial,
Function2, Eval> mapper) {
return EitherOf.narrowK(value).fold(cons(initial), a -> mapper.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> mapper) {
return EitherOf.narrowK(value).fold(
l -> applicative.pure(Either.left(l)),
t -> applicative.map(mapper.apply(t), r -> Either.right(r)));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy