com.github.tonivade.purefun.instances.MonadMTL 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.Precondition.checkNonNull;
import static com.github.tonivade.purefun.transformer.EitherTOf.toEitherT;
import static com.github.tonivade.purefun.transformer.KleisliOf.toKleisli;
import static com.github.tonivade.purefun.transformer.StateTOf.toStateT;
import com.github.tonivade.purefun.Function1;
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.instances.MonadMTL.EffectE;
import com.github.tonivade.purefun.instances.MonadMTL.EffectE_;
import com.github.tonivade.purefun.instances.MonadMTL.EffectR;
import com.github.tonivade.purefun.instances.MonadMTL.EffectR_;
import com.github.tonivade.purefun.instances.MonadMTL.EffectS_;
import com.github.tonivade.purefun.transformer.EitherT;
import com.github.tonivade.purefun.transformer.EitherT_;
import com.github.tonivade.purefun.transformer.Kleisli;
import com.github.tonivade.purefun.transformer.Kleisli_;
import com.github.tonivade.purefun.transformer.StateT;
import com.github.tonivade.purefun.transformer.StateT_;
import com.github.tonivade.purefun.type.Either;
import com.github.tonivade.purefun.typeclasses.Monad;
import com.github.tonivade.purefun.typeclasses.MonadError;
import com.github.tonivade.purefun.typeclasses.MonadReader;
import com.github.tonivade.purefun.typeclasses.MonadState;
public class MonadMTL
implements Monad, MonadError, MonadState, MonadReader {
private final Monad monad;
private final MonadError monadErrorE;
private final Monad monadR;
private final MonadError, S>, E> monadErrorS;
private final MonadReader, S>, R> monadReaderS;
private final MonadState, S>, S> monadStateS;
public MonadMTL(Monad monad) {
this.monad = checkNonNull(monad);
this.monadErrorE = new EffectEMonadError<>(monad);
this.monadR = new EffectRMonad<>(monad);
this.monadErrorS = StateTInstances.monadError(new EffectRMonadError<>(monad));
this.monadReaderS = StateTInstances.monadReader(new EffectRMonadReader<>(monad));
this.monadStateS = StateTInstances.monadState(monadR);
}
@Override
public EffectS pure(A value) {
return new EffectS<>(monadStateS.pure(value));
}
@Override
public EffectS flatMap(Kind value,
Function1 super A, ? extends Kind> map) {
return new EffectS<>(monadStateS.flatMap(
value.fix(EffectS::narrowK).value(),
x -> map.apply(x).fix(EffectS::narrowK).value()));
}
@Override
public EffectS get() {
return new EffectS<>(monadStateS.get());
}
@Override
public EffectS set(S state) {
return new EffectS<>(monadStateS.set(state));
}
@Override
public EffectS raiseError(E error) {
return new EffectS<>(monadErrorS.raiseError(error));
}
@Override
public EffectS handleErrorWith(
Kind value, Function1 super E, ? extends Kind> handler) {
return new EffectS<>(monadErrorS.handleErrorWith(
value.fix(EffectS::narrowK).value(),
error -> handler.apply(error).fix(EffectS::narrowK).value()));
}
@Override
public EffectS ask() {
return new EffectS<>(monadReaderS.ask());
}
public EffectE effectE(Kind> value) {
return new EffectE<>(EitherT.of(monad, value));
}
public EffectR effectR(EffectE effect0) {
return new EffectR<>(Kleisli.of(monadErrorE, config -> effect0));
}
public EffectS effectS(EffectR effect1) {
return new EffectS<>(StateT.state(monadR, state -> monadR.map(effect1, x -> Tuple.of(state, x))));
}
public EffectS effect(Kind> value) {
return effectS(effectR(effectE(value)));
}
public static final class EffectE_ implements Witness { }
public static final class EffectR_ implements Witness { }
public static final class EffectS_ implements Witness { }
public static final class EffectE implements Kind {
private final EitherT value;
public EffectE(Kind, E>, A> value) {
this.value = value.fix(toEitherT());
}
public EitherT value() {
return value;
}
public Kind> run() {
return value.value();
}
@SuppressWarnings("unchecked")
public static EffectE narrowK(Kind hkt) {
return (EffectE) hkt;
}
}
public static final class EffectR implements Kind {
private final Kleisli value;
public EffectR(Kind, R>, A> value) {
this.value = value.fix(toKleisli());
}
public Kleisli value() {
return value;
}
public EffectE run(R config) {
return value.run(config).fix(EffectE::narrowK);
}
@SuppressWarnings("unchecked")
public static EffectR narrowK(Kind hkt) {
return (EffectR) hkt;
}
}
public static final class EffectS implements Kind {
private final StateT value;
public EffectS(Kind, S>, A> value) {
this.value = value.fix(toStateT());
}
public StateT value() {
return value;
}
public EffectR> run(S state) {
return value.run(state).fix(EffectR::narrowK);
}
@SuppressWarnings("unchecked")
public static EffectS narrowK(Kind hkt) {
return (EffectS) hkt;
}
}
}
class EffectEMonadError implements MonadError {
private final MonadError, E>, E> monad;
public EffectEMonadError(Monad monad) {
this.monad = EitherTInstances.monadError(monad);
}
@Override
public EffectE pure(A value) {
return new EffectE<>(monad.pure(value));
}
@Override
public EffectE flatMap(Kind value,
Function1 super A, ? extends Kind> map) {
return new EffectE<>(monad.flatMap(
value.fix(EffectE::narrowK).value(),
x -> map.apply(x).fix(EffectE::narrowK).value()));
}
@Override
public EffectE raiseError(E error) {
return new EffectE<>(monad.raiseError(error));
}
@Override
public EffectE handleErrorWith(Kind value,
Function1 super E, ? extends Kind> handler) {
return new EffectE<>(monad.handleErrorWith(value.fix(EffectE::narrowK).value(),
error -> handler.apply(error).fix(EffectE::narrowK).value()));
}
}
class EffectRMonad implements Monad {
private final Monad, R>> monad;
public EffectRMonad(Monad monad) {
this.monad = KleisliInstances.monad(new EffectEMonadError(monad));
}
@Override
public EffectR pure(A value) {
return new EffectR<>(monad.pure(value));
}
@Override
public EffectR flatMap(Kind value,
Function1 super A, ? extends Kind> map) {
return new EffectR<>(monad.flatMap(value.fix(EffectR::narrowK).value(),
t -> map.apply(t).fix(EffectR::narrowK).value()));
}
}
class EffectRMonadReader extends EffectRMonad implements MonadReader {
private final MonadReader, R>, R> monad;
public EffectRMonadReader(Monad monad) {
super(monad);
this.monad = KleisliInstances.monadReader(new EffectEMonadError(monad));
}
@Override
public EffectR ask() {
return new EffectR<>(monad.ask());
}
}
class EffectRMonadError extends EffectRMonad implements MonadError {
private final MonadError, R>, E> monadError;
public EffectRMonadError(Monad monad) {
super(monad);
this.monadError = KleisliInstances.monadError(new EffectEMonadError(monad));
}
@Override
public EffectR raiseError(E error) {
return new EffectR<>(monadError.raiseError(error));
}
@Override
public EffectR handleErrorWith(
Kind value, Function1 super E, ? extends Kind> handler) {
return new EffectR<>(monadError.handleErrorWith(
value.fix(EffectR::narrowK).value(),
error -> handler.apply(error).fix(EffectR::narrowK).value()));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy