com.github.tonivade.purefun.instances.FutureInstances Maven / Gradle / Ivy
/*
* Copyright (c) 2018-2020, 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 java.time.Duration;
import java.util.concurrent.Executor;
import com.github.tonivade.purefun.Consumer1;
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.concurrent.Future;
import com.github.tonivade.purefun.concurrent.FutureOf;
import com.github.tonivade.purefun.concurrent.Future_;
import com.github.tonivade.purefun.typeclasses.Applicative;
import com.github.tonivade.purefun.typeclasses.Bracket;
import com.github.tonivade.purefun.typeclasses.Defer;
import com.github.tonivade.purefun.typeclasses.Functor;
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;
public interface FutureInstances {
static Functor functor() {
return FutureFunctor.INSTANCE;
}
static Applicative applicative() {
return applicative(Future.DEFAULT_EXECUTOR);
}
static Applicative applicative(Executor executor) {
return FutureApplicative.instance(checkNonNull(executor));
}
static Monad monad() {
return monad(Future.DEFAULT_EXECUTOR);
}
static Monad monad(Executor executor) {
return FutureMonad.instance(checkNonNull(executor));
}
static MonadError monadError() {
return monadError(Future.DEFAULT_EXECUTOR);
}
static MonadError monadError(Executor executor) {
return FutureMonadThrow.instance(checkNonNull(executor));
}
static MonadDefer monadDefer() {
return monadDefer(Future.DEFAULT_EXECUTOR);
}
static MonadDefer monadDefer(Executor executor) {
return FutureMonadDefer.instance(checkNonNull(executor));
}
}
interface FutureFunctor extends Functor {
FutureFunctor INSTANCE = new FutureFunctor() {};
@Override
default Kind map(Kind value, Function1 mapper) {
return FutureOf.narrowK(value).map(mapper);
}
}
interface ExecutorHolder {
Executor executor();
}
interface FuturePure extends Applicative, ExecutorHolder {
@Override
default Kind pure(T value) {
return Future.success(executor(), value);
}
}
interface FutureApplicative extends FuturePure {
static FutureApplicative instance(Executor executor) {
return () -> executor;
}
@Override
default Kind ap(Kind value, Kind> apply) {
return FutureOf.narrowK(value).flatMap(t -> FutureOf.narrowK(apply).map(f -> f.apply(t)));
}
}
interface FutureMonad extends FuturePure, Monad {
static FutureMonad instance(Executor executor) {
return () -> executor;
}
@Override
default Kind flatMap(Kind value,
Function1> map) {
return FutureOf.narrowK(value).flatMap(map.andThen(FutureOf::narrowK));
}
/**
* XXX In order to create real parallel computations, we need to override ap to use the
* applicative version of the ap method
*/
@Override
default Kind ap(Kind value, Kind> apply) {
return FutureInstances.applicative().ap(value, apply);
}
}
interface FutureMonadThrow extends FutureMonad, MonadThrow {
static FutureMonadThrow instance(Executor executor) {
return () -> executor;
}
@Override
default Kind raiseError(Throwable error) {
return Future.failure(executor(), error);
}
@Override
default Kind handleErrorWith(Kind value,
Function1> handler) {
return FutureOf.narrowK(value).fold(handler.andThen(FutureOf::narrowK),
success -> Future.success(executor(), success)).flatMap(identity());
}
}
interface FutureDefer extends Defer, ExecutorHolder {
@Override
default Kind defer(Producer> defer) {
return Future.defer(executor(), defer.map(FutureOf::narrowK)::get);
}
}
interface FutureBracket extends Bracket, ExecutorHolder {
@Override
default Kind bracket(Kind acquire, Function1> use, Consumer1 release) {
return Future.bracket(executor(), FutureOf.narrowK(acquire), use.andThen(FutureOf::narrowK), release);
}
}
interface FutureMonadDefer extends MonadDefer, FutureMonadThrow, FutureDefer, FutureBracket {
static FutureMonadDefer instance(Executor executor) {
return () -> executor;
}
@Override
default Kind sleep(Duration duration) {
return Future.sleep(executor(), duration);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy