com.github.tonivade.purefun.instances.OptionTInstances 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.identity;
import static com.github.tonivade.purefun.Precondition.checkNonNull;
import static com.github.tonivade.purefun.Unit.unit;
import java.time.Duration;
import java.util.NoSuchElementException;
import com.github.tonivade.purefun.Eq;
import com.github.tonivade.purefun.Function1;
import com.github.tonivade.purefun.Kind;
import com.github.tonivade.purefun.Producer;
import com.github.tonivade.purefun.Unit;
import com.github.tonivade.purefun.Witness;
import com.github.tonivade.purefun.transformer.OptionT;
import com.github.tonivade.purefun.transformer.OptionTOf;
import com.github.tonivade.purefun.transformer.OptionT_;
import com.github.tonivade.purefun.type.Option;
import com.github.tonivade.purefun.typeclasses.Bracket;
import com.github.tonivade.purefun.typeclasses.Defer;
import com.github.tonivade.purefun.typeclasses.Monad;
import com.github.tonivade.purefun.typeclasses.MonadDefer;
import com.github.tonivade.purefun.typeclasses.MonadError;
import com.github.tonivade.purefun.typeclasses.MonadThrow;
import com.github.tonivade.purefun.typeclasses.Reference;
public interface OptionTInstances {
static Eq, T>> eq(Eq>> eq) {
return (a, b) -> eq.eqv(OptionTOf.narrowK(a).value(), OptionTOf.narrowK(b).value());
}
static Monad> monad(Monad monadF) {
return OptionTMonad.instance(checkNonNull(monadF));
}
static MonadError, Unit> monadError(Monad monadF) {
return OptionTMonadErrorFromMonad.instance(checkNonNull(monadF));
}
static MonadError, E> monadError(MonadError monadErrorF) {
return OptionTMonadErrorFromMonadError.instance(checkNonNull(monadErrorF));
}
static MonadThrow> monadThrow(MonadThrow monadThrowF) {
return OptionTMonadThrow.instance(checkNonNull(checkNonNull(monadThrowF)));
}
static MonadDefer> monadDefer(MonadDefer monadDeferF) {
return OptionTMonadDefer.instance(checkNonNull(monadDeferF));
}
static Reference, A> ref(MonadDefer monadF, A value) {
return Reference.of(monadDefer(monadF), value);
}
}
interface OptionTMonad extends Monad> {
static OptionTMonad instance(Monad monadF) {
return () -> monadF;
}
Monad monadF();
@Override
default OptionT pure(T value) {
return OptionT.some(monadF(), value);
}
@Override
default OptionT flatMap(Kind, ? extends T> value,
Function1 super T, ? extends Kind, ? extends R>> map) {
return OptionTOf.narrowK(value).flatMap(map.andThen(OptionTOf::narrowK));
}
}
interface OptionTMonadErrorFromMonad
extends MonadError, Unit>, OptionTMonad {
static OptionTMonadErrorFromMonad instance(Monad monadF) {
return () -> monadF;
}
@Override
default OptionT raiseError(Unit error) {
return OptionT.none(monadF());
}
@Override
default OptionT handleErrorWith(Kind, A> value,
Function1 super Unit, ? extends Kind, ? extends A>> handler) {
return OptionT.of(monadF(),
monadF().flatMap(OptionTOf.narrowK(value).value(),
option -> option.fold(
() -> handler.andThen(OptionTOf::narrowK).apply(unit()).value(),
a -> monadF().pure(Option.some(a)))));
}
}
interface OptionTMonadErrorFromMonadError
extends MonadError, E>, OptionTMonad {
static OptionTMonadErrorFromMonadError instance(MonadError monadF) {
return () -> monadF;
}
@Override
MonadError monadF();
@Override
default OptionT raiseError(E error) {
return OptionT.of(monadF(), monadF().raiseError(error));
}
@Override
default OptionT handleErrorWith(Kind, A> value,
Function1 super E, ? extends Kind, ? extends A>> handler) {
return OptionT.of(monadF(),
monadF().handleErrorWith(
OptionTOf.narrowK(value).value(), error -> handler.andThen(OptionTOf::narrowK).apply(error).value()));
}
}
interface OptionTMonadThrow
extends MonadThrow>,
OptionTMonadErrorFromMonadError {
static OptionTMonadThrow instance(MonadThrow monadThrowF) {
return () -> monadThrowF;
}
}
interface OptionTDefer extends Defer> {
MonadDefer monadF();
@Override
default OptionT defer(Producer extends Kind, ? extends A>> defer) {
return OptionT.of(monadF(), monadF().defer(() -> defer.map(OptionTOf::narrowK).get().value()));
}
}
interface OptionTBracket extends Bracket, Throwable> {
Bracket monadF();
@Override
default OptionT bracket(
Kind, ? extends A> acquire,
Function1 super A, ? extends Kind, ? extends B>> use,
Function1 super A, ? extends Kind, Unit>> release) {
Kind> bracket =
monadF().bracket(
acquire.fix(OptionTOf::narrowK).value(),
option -> option.fold(
() -> monadF().raiseError(new NoSuchElementException("could not acquire resource")),
value -> use.andThen(OptionTOf::narrowK).apply(value).value()),
option -> {
Kind, Unit> fold = option.fold(() -> pure(Unit.unit()), release::apply);
Kind> value = fold.fix(OptionTOf::narrowK).value();
return monadF().map(value, x -> x.fold(Unit::unit, identity()));
});
return OptionT.of(monadF(), bracket);
}
}
interface OptionTMonadDefer
extends OptionTMonadThrow,
OptionTDefer,
OptionTBracket,
MonadDefer> {
static OptionTMonadDefer instance(MonadDefer monadDeferF) {
return () -> monadDeferF;
}
@Override
default OptionT sleep(Duration duration) {
return OptionT.of(monadF(), monadF().map(monadF().sleep(duration), Option::some));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy