All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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 java.time.Duration;
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.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.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;

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);
  }
}

interface TaskFunctor extends Functor {

  TaskFunctor INSTANCE = new TaskFunctor() {};

  @Override
  default  Task
          map(Kind value, Function1 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 TaskOf.narrowK(apply).flatMap(map -> TaskOf.narrowK(value).map(map));
  }
}

interface TaskMonad extends TaskPure, Monad {

  TaskMonad INSTANCE = new TaskMonad() {};

  @Override
  default  Task
          flatMap(Kind value,
                  Function1> 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> handler) {
    // XXX: java8 fails to infer types, I have to do this in steps
    Function1> 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> defer) {
    return Task.defer(() -> defer.map(TaskOf::narrowK).get());
  }
}

interface TaskBracket extends Bracket {

  @Override
  default  Task
          bracket(Kind acquire,
                  Function1> use,
                  Consumer1 release) {
    return Task.bracket(acquire.fix(TaskOf::narrowK), use.andThen(TaskOf::narrowK), release);
  }
}

interface TaskMonadDefer
    extends MonadDefer, TaskMonadThrow, TaskDefer, TaskBracket {

  TaskMonadDefer INSTANCE = new TaskMonadDefer() {};

  @Override
  default Task sleep(Duration duration) {
    return Task.sleep(duration);
  }
}