com.github.tonivade.purefun.instances.OptionInstances 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.Producer.cons;
import static com.github.tonivade.purefun.Unit.unit;
import static com.github.tonivade.purefun.type.OptionOf.toOption;
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.Tuple;
import com.github.tonivade.purefun.Tuple2;
import com.github.tonivade.purefun.Unit;
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.Option;
import com.github.tonivade.purefun.type.OptionOf;
import com.github.tonivade.purefun.type.Option_;
import com.github.tonivade.purefun.typeclasses.Alternative;
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.MonoidK;
import com.github.tonivade.purefun.typeclasses.SemigroupK;
import com.github.tonivade.purefun.typeclasses.Semigroupal;
import com.github.tonivade.purefun.typeclasses.Traverse;
public interface OptionInstances {
static Eq> eq(Eq eqSome) {
return (a, b) -> {
if (a instanceof Option.Some someA && b instanceof Option.Some someB) {
return eqSome.eqv(someA.getOrElseThrow(), someB.getOrElseThrow());
}
return a instanceof Option.None && b instanceof Option.None;
};
}
static Functor functor() {
return OptionFunctor.INSTANCE;
}
static Applicative applicative() {
return OptionApplicative.INSTANCE;
}
static Alternative alternative() {
return OptionAlternative.INSTANCE;
}
static Monad monad() {
return OptionMonad.INSTANCE;
}
static MonadError monadError() {
return OptionMonadError.INSTANCE;
}
static Traverse traverse() {
return OptionTraverse.INSTANCE;
}
static Semigroupal semigroupal() {
return OptionSemigroupal.INSTANCE;
}
static Foldable foldable() {
return OptionFoldable.INSTANCE;
}
}
interface OptionFunctor extends Functor {
OptionFunctor INSTANCE = new OptionFunctor() {};
@Override
default Kind map(Kind value, Function1 super T, ? extends R> mapper) {
return OptionOf.narrowK(value).map(mapper);
}
}
interface OptionPure extends Applicative {
@Override
default Kind pure(T value) {
return Option.some(value);
}
}
interface OptionApplicative extends OptionPure {
OptionApplicative INSTANCE = new OptionApplicative() {};
@Override
default Kind ap(Kind value,
Kind> apply) {
return value.fix(toOption()).flatMap(t -> OptionOf.narrowK(apply).map(f -> f.apply(t)));
}
}
interface OptionMonad extends OptionPure, Monad {
OptionMonad INSTANCE = new OptionMonad() {};
@Override
default Kind flatMap(Kind value,
Function1 super T, ? extends Kind> map) {
return value.fix(toOption()).flatMap(map.andThen(OptionOf::narrowK));
}
}
interface OptionSemigroupK extends SemigroupK {
OptionSemigroupK INSTANCE = new OptionSemigroupK() {};
@Override
default Kind combineK(Kind t1, Kind t2) {
return OptionOf.narrowK(t1).fold(cons(OptionOf.narrowK(t2)), Option::some);
}
}
interface OptionMonoidK extends OptionSemigroupK, MonoidK {
OptionMonoidK INSTANCE = new OptionMonoidK() {};
@Override
default Kind zero() {
return Option.none();
}
}
interface OptionAlternative extends OptionMonoidK, OptionApplicative, Alternative {
OptionAlternative INSTANCE = new OptionAlternative() {};
}
interface OptionMonadError extends OptionMonad, MonadError {
OptionMonadError INSTANCE = new OptionMonadError() {};
@Override
default Kind raiseError(Unit error) {
return Option.none();
}
@Override
default Kind handleErrorWith(Kind value,
Function1 super Unit, ? extends Kind> handler) {
return OptionOf.narrowK(value).fold(() -> OptionOf.narrowK(handler.apply(unit())), this::pure);
}
}
interface OptionFoldable extends Foldable {
OptionFoldable INSTANCE = new OptionFoldable() {};
@Override
default B foldLeft(Kind value, B initial, Function2 super B, ? super A, ? extends B> mapper) {
return OptionOf.narrowK(value).fold(cons(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 OptionOf.narrowK(value).fold(
cons(initial).andThen(EvalOf::narrowK), a -> mapper.andThen(EvalOf::narrowK).apply(a, initial));
}
}
interface OptionTraverse extends Traverse, OptionFoldable {
OptionTraverse INSTANCE = new OptionTraverse() {};
@Override
default Kind> traverse(
Applicative applicative, Kind value,
Function1 super T, ? extends Kind> mapper) {
return value.fix(toOption()).fold(
() -> applicative.pure(Option.none().kind()),
t -> {
Kind apply = mapper.apply(t);
return applicative.map(apply, Option::some);
});
}
}
interface OptionSemigroupal extends Semigroupal {
OptionSemigroupal INSTANCE = new OptionSemigroupal() {};
@Override
default Kind> product(Kind fa, Kind fb) {
return OptionOf.narrowK(fa).flatMap(a -> OptionOf.narrowK(fb).map(b -> Tuple.of(a, b)));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy