com.github.tonivade.purefun.instances.TryInstances 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.Eval;
import com.github.tonivade.purefun.type.EvalOf;
import com.github.tonivade.purefun.type.Try;
import com.github.tonivade.purefun.type.TryOf;
import com.github.tonivade.purefun.type.Try_;
import com.github.tonivade.purefun.typeclasses.Applicative;
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 TryInstances {
static Eq> eq(Eq eqSuccess) {
final Eq eqFailure = Eq.throwable();
return (a, b) -> {
if (a instanceof Try.Failure failureA && b instanceof Try.Failure failureB) {
return eqFailure.eqv(failureA.getCause(), failureB.getCause());
}
if (a instanceof Try.Success successA && b instanceof Try.Success successB) {
return eqSuccess.eqv(successA.getOrElseThrow(), successB.getOrElseThrow());
}
return false;
};
}
static Functor functor() {
return TryFunctor.INSTANCE;
}
static Applicative applicative() {
return TryApplicative.INSTANCE;
}
static Monad monad() {
return TryMonad.INSTANCE;
}
static MonadError monadError() {
return TryMonadError.INSTANCE;
}
static MonadThrow monadThrow() {
return TryMonadThrow.INSTANCE;
}
static Foldable foldable() {
return TryFoldable.INSTANCE;
}
static Traverse traverse() {
return TryTraverse.INSTANCE;
}
}
interface TryFunctor extends Functor {
TryFunctor INSTANCE = new TryFunctor() {};
@Override
default Kind map(Kind value, Function1 super T, ? extends R> mapper) {
return TryOf.narrowK(value).map(mapper);
}
}
interface TryPure extends Applicative {
@Override
default Kind pure(T value) {
return Try.success(value);
}
}
interface TryApplicative extends TryPure {
TryApplicative INSTANCE = new TryApplicative() {};
@Override
default Kind ap(Kind value,
Kind> apply) {
return TryOf.narrowK(value).flatMap(t -> TryOf.narrowK(apply).map(f -> f.apply(t)));
}
}
interface TryMonad extends TryPure, Monad {
TryMonad INSTANCE = new TryMonad() {};
@Override
default Kind flatMap(Kind value,
Function1 super T, ? extends Kind> map) {
return TryOf.narrowK(value).flatMap(map.andThen(TryOf::narrowK));
}
}
interface TryMonadError extends TryMonad, MonadError {
TryMonadError INSTANCE = new TryMonadError() {};
@Override
default Kind raiseError(Throwable error) {
return Try.failure(error);
}
@Override
default Kind handleErrorWith(Kind value,
Function1 super Throwable, ? extends Kind> handler) {
return TryOf.narrowK(value).fold(handler.andThen(TryOf::narrowK), Try::success);
}
}
interface TryMonadThrow extends TryMonadError, MonadThrow {
TryMonadThrow INSTANCE = new TryMonadThrow() {};
}
interface TryFoldable extends Foldable {
TryFoldable INSTANCE = new TryFoldable() {};
@Override
default B foldLeft(Kind value, B initial, Function2 super B, ? super A, ? extends B> mapper) {
return TryOf.narrowK(value).fold(t -> initial, a -> mapper.apply(initial, a));
}
@Override
default Eval foldRight(Kind value, Eval extends B> initial,
Function2 super A, ? super Eval extends B>, ? extends Eval extends B>> mapper) {
return TryOf.narrowK(value).fold(
cons(initial).andThen(EvalOf::narrowK),
a -> mapper.andThen(EvalOf::narrowK).apply(a, initial));
}
}
interface TryTraverse extends Traverse, TryFoldable {
TryTraverse INSTANCE = new TryTraverse() {};
@Override
default Kind> traverse(
Applicative applicative, Kind value,
Function1 super T, ? extends Kind> mapper) {
return TryOf.narrowK(value).fold(
t -> applicative.pure(Try.failure(t).kind()),
t -> {
Kind apply = mapper.apply(t);
return applicative.map(apply, x -> Try.success(x));
});
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy