com.github.tonivade.purefun.instances.TaskInstances 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.concurrent.FutureOf.toFuture;
import static com.github.tonivade.purefun.effect.TaskOf.toTask;
import static com.github.tonivade.purefun.instances.FutureInstances.async;
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.effect.Task;
import com.github.tonivade.purefun.effect.TaskOf;
import com.github.tonivade.purefun.effect.Task_;
import com.github.tonivade.purefun.typeclasses.Applicative;
import com.github.tonivade.purefun.typeclasses.Bracket;
import com.github.tonivade.purefun.typeclasses.Console;
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;
import com.github.tonivade.purefun.typeclasses.Reference;
import com.github.tonivade.purefun.typeclasses.Resource;
import com.github.tonivade.purefun.typeclasses.Runtime;
public interface TaskInstances {
static Functor functor() {
return TaskFunctor.INSTANCE;
}
static Applicative applicative() {
return TaskApplicative.INSTANCE;
}
static Monad monad() {
return TaskMonad.INSTANCE;
}
static MonadError monadError() {
return TaskMonadError.INSTANCE;
}
static MonadThrow monadThrow() {
return TaskMonadThrow.INSTANCE;
}
static MonadDefer monadDefer() {
return TaskMonadDefer.INSTANCE;
}
static Reference ref(A value) {
return Reference.of(monadDefer(), value);
}
static Resource resource(Task acquire) {
return resource(acquire, AutoCloseable::close);
}
static Resource resource(Task acquire, Consumer1 release) {
return Resource.from(monadDefer(), acquire, release);
}
static Console console() {
return TaskConsole.INSTANCE;
}
static Runtime runtime() {
return TaskRuntime.INSTANCE;
}
}
interface TaskFunctor extends Functor {
TaskFunctor INSTANCE = new TaskFunctor() {};
@Override
default Task map(Kind value, Function1 super A, ? extends B> map) {
return TaskOf.narrowK(value).map(map);
}
}
interface TaskPure extends Applicative {
@Override
default Task pure(A value) {
return Task.pure(value);
}
}
interface TaskApplicative extends TaskPure {
TaskApplicative INSTANCE = new TaskApplicative() {};
@Override
default Task
ap(Kind value,
Kind> apply) {
return value.fix(TaskOf::narrowK).ap(apply.fix(TaskOf::narrowK));
}
}
interface TaskMonad extends TaskPure, Monad {
TaskMonad INSTANCE = new TaskMonad() {};
@Override
default Task
flatMap(Kind value,
Function1 super A, ? extends Kind> map) {
return TaskOf.narrowK(value).flatMap(map.andThen(TaskOf::narrowK));
}
}
interface TaskMonadError extends TaskMonad, MonadError {
TaskMonadError INSTANCE = new TaskMonadError() {};
@Override
default Task raiseError(Throwable error) {
return Task.raiseError(error);
}
@Override
default Task handleErrorWith(
Kind value,
Function1 super Throwable, ? extends Kind> handler) {
// XXX: java8 fails to infer types, I have to do this in steps
Function1 super Throwable, Task> mapError = handler.andThen(TaskOf::narrowK);
Function1> map = Task::pure;
Task task = TaskOf.narrowK(value);
return task.foldM(mapError, map);
}
}
interface TaskMonadThrow extends TaskMonadError, MonadThrow {
TaskMonadThrow INSTANCE = new TaskMonadThrow() {};
}
interface TaskDefer extends Defer {
@Override
default Task
defer(Producer extends Kind> defer) {
return Task.defer(() -> defer.map(TaskOf::narrowK).get());
}
}
interface TaskBracket extends TaskMonadError, Bracket {
@Override
default Task
bracket(Kind acquire,
Function1 super A, ? extends Kind> use,
Consumer1 super A> release) {
return Task.bracket(acquire.fix(TaskOf::narrowK), use.andThen(TaskOf::narrowK), release);
}
}
interface TaskMonadDefer
extends MonadDefer, TaskDefer, TaskBracket {
TaskMonadDefer INSTANCE = new TaskMonadDefer() {};
@Override
default Task sleep(Duration duration) {
return Task.sleep(duration);
}
}
final class TaskConsole implements Console {
public static final TaskConsole INSTANCE = new TaskConsole();
private final SystemConsole console = new SystemConsole();
@Override
public Task readln() {
return Task.task(console::readln);
}
@Override
public Task println(String text) {
return Task.exec(() -> console.println(text));
}
}
interface TaskRuntime extends Runtime {
TaskRuntime INSTANCE = new TaskRuntime() {};
@Override
default T run(Kind value) {
return value.fix(toTask()).safeRunSync().getOrElseThrow();
}
@Override
default Future parRun(Kind value, Executor executor) {
return value.fix(toTask()).foldMap(async(executor)).fix(toFuture());
}
} © 2015 - 2025 Weber Informatics LLC | Privacy Policy