com.github.tonivade.purefun.instances.EitherInstances Maven / Gradle / Ivy
/*
* Copyright (c) 2018-2019, 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.Higher1;
import com.github.tonivade.purefun.Higher2;
import com.github.tonivade.purefun.Instance;
import com.github.tonivade.purefun.Kind;
import com.github.tonivade.purefun.Pattern2;
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;
public interface EitherInstances {
static Eq> 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(Either.narrowK(a), Either.narrowK(b));
}
static Functor> functor() {
return new EitherFunctor() {};
}
static Bifunctor bifunctor() {
return new EitherBifunctor() {};
}
static Applicative> applicative() {
return new EitherApplicative() {};
}
static Monad> monad() {
return new EitherMonad() {};
}
static MonadError, L> monadError() {
return new EitherMonadError() {};
}
static MonadThrow> monadThrow() {
return new EitherMonadThrow() {};
}
static Foldable> foldable() {
return new EitherFoldable() {};
}
static Traverse> traverse() {
return new EitherTraverse() {};
}
}
@Instance
interface EitherFunctor extends Functor> {
@Override
default Either map(Higher1, T> value, Function1 map) {
return Either.narrowK(value).map(map);
}
}
@Instance
interface EitherBifunctor extends Bifunctor {
@Override
default Either bimap(Higher2 value,
Function1 leftMap, Function1 rightMap) {
return Either.narrowK(value).mapLeft(leftMap).map(rightMap);
}
}
@Instance
interface EitherPure extends Applicative> {
@Override
default Either pure(T value) {
return Either.right(value);
}
}
@Instance
interface EitherApplicative extends EitherPure {
@Override
default Either ap(Higher1, T> value,
Higher1, Function1> apply) {
return Either.narrowK(value).flatMap(t -> Either.narrowK(apply).map(f -> f.apply(t)));
}
}
@Instance
interface EitherMonad extends EitherPure, Monad> {
@Override
default Either flatMap(Higher1, T> value,
Function1, R>> map) {
return Either.narrowK(value).flatMap(map.andThen(Either::narrowK));
}
}
@Instance
interface EitherMonadError extends EitherMonad, MonadError, L> {
@Override
default Either raiseError(L error) {
return Either.left(error);
}
@Override
default Either handleErrorWith(Higher1, A> value,
Function1, A>> handler) {
return Either.narrowK(value).fold(handler.andThen(Either::narrowK), Either::right);
}
}
@Instance
interface EitherMonadThrow extends EitherMonadError, MonadThrow> { }
@Instance
interface EitherFoldable extends Foldable> {
@Override
default B foldLeft(Higher1, A> value, B initial, Function2 mapper) {
return Either.narrowK(value).fold(cons(initial), a -> mapper.apply(initial, a));
}
@Override
default Eval foldRight(Higher1, A> value, Eval initial,
Function2, Eval> mapper) {
return Either.narrowK(value).fold(cons(initial), a -> mapper.apply(a, initial));
}
}
@Instance
interface EitherTraverse extends Traverse>, EitherFoldable {
@Override
default Higher1, R>> traverse(
Applicative applicative, Higher1, T> value,
Function1> mapper) {
return Either.narrowK(value).fold(
l -> applicative.pure(Either.left(l)),
t -> applicative.map(mapper.apply(t), Either::right));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy