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

com.github.tonivade.purefun.instances.EIOInstances 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.effect.EIOOf.toEIO;
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.Tuple2;
import com.github.tonivade.purefun.Unit;
import com.github.tonivade.purefun.concurrent.Future;
import com.github.tonivade.purefun.data.Sequence;
import com.github.tonivade.purefun.effect.EIO;
import com.github.tonivade.purefun.effect.EIOOf;
import com.github.tonivade.purefun.effect.EIO_;
import com.github.tonivade.purefun.effect.UIO;
import com.github.tonivade.purefun.type.Either;
import com.github.tonivade.purefun.type.Try;
import com.github.tonivade.purefun.typeclasses.Applicative;
import com.github.tonivade.purefun.typeclasses.Async;
import com.github.tonivade.purefun.typeclasses.Bracket;
import com.github.tonivade.purefun.typeclasses.Concurrent;
import com.github.tonivade.purefun.typeclasses.Defer;
import com.github.tonivade.purefun.typeclasses.Fiber;
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.Runtime;

@SuppressWarnings("unchecked")
public interface EIOInstances {

  static  Functor> functor() {
    return EIOFunctor.INSTANCE;
  }

  static  Applicative> applicative() {
    return EIOApplicative.INSTANCE;
  }

  static  Monad> monad() {
    return EIOMonad.INSTANCE;
  }

  static  MonadError, E> monadError() {
    return EIOMonadError.INSTANCE;
  }

  static MonadThrow> monadThrow() {
    return EIOMonadThrow.INSTANCE;
  }

  static MonadDefer> monadDefer() {
    return EIOMonadDefer.INSTANCE;
  }

  static Async> async() {
    return EIOAsync.INSTANCE;
  }

  static Concurrent> concurrent() {
    return concurrent(Future.DEFAULT_EXECUTOR);
  }

  static Concurrent> concurrent(Executor executor) {
    return EIOConcurrent.instance(executor);
  }
  
  static  Runtime> runtime() {
    return EIORuntime.INSTANCE;
  }
}

interface EIOFunctor extends Functor> {

  @SuppressWarnings("rawtypes")
  EIOFunctor INSTANCE = new EIOFunctor() {};

  @Override
  default  EIO
          map(Kind, ? extends A> value, Function1 map) {
    return EIOOf.narrowK(value).map(map);
  }
}

interface EIOPure extends Applicative> {

  @Override
  default  EIO pure(A value) {
    return EIO.pure(value);
  }
}

interface EIOApplicative extends EIOPure {

  @SuppressWarnings("rawtypes")
  EIOApplicative INSTANCE = new EIOApplicative() {};

  @Override
  default  EIO
          ap(Kind, ? extends A> value,
             Kind, ? extends Function1> apply) {
    return value.fix(EIOOf::narrowK).ap(apply.fix(EIOOf::narrowK));
  }
}

interface EIOMonad extends EIOPure, Monad> {

  @SuppressWarnings("rawtypes")
  EIOMonad INSTANCE = new EIOMonad() {};

  @Override
  default  EIO
          flatMap(Kind, ? extends A> value,
                  Function1, ? extends B>> map) {
    return value.fix(toEIO()).flatMap(map.andThen(EIOOf::narrowK));
  }
}

interface EIOMonadError extends EIOMonad, MonadError, E> {

  @SuppressWarnings("rawtypes")
  EIOMonadError INSTANCE = new EIOMonadError() {};

  @Override
  default  EIO raiseError(E error) {
    return EIO.raiseError(error);
  }

  @Override
  default  EIO handleErrorWith(
      Kind, A> value,
      Function1, ? extends A>> handler) {
    // XXX: java8 fails to infer types, I have to do this in steps
    Function1> mapError = handler.andThen(EIOOf::narrowK);
    Function1> map = EIO::pure;
    EIO eio = EIOOf.narrowK(value);
    return eio.foldM(mapError, map);
  }
}

interface EIOMonadThrow
    extends EIOMonadError,
            MonadThrow> {

  EIOMonadThrow INSTANCE = new EIOMonadThrow() {};
}

interface EIODefer extends Defer> {

  @Override
  default  EIO
          defer(Producer, ? extends A>> defer) {
    return EIO.defer(defer::get);
  }
}

interface EIOBracket extends EIOMonadError, Bracket, E> {

  @Override
  default  EIO
          bracket(Kind, ? extends A> acquire,
                  Function1, ? extends B>> use,
                  Function1, Unit>> release) {
    return EIO.bracket(acquire, use, release);
  }
}

interface EIOMonadDefer
    extends MonadDefer>, EIODefer, EIOBracket {

  EIOMonadDefer INSTANCE = new EIOMonadDefer() {};

  @Override
  default EIO sleep(Duration duration) {
    return UIO.sleep(duration).toEIO();
  }
}

interface EIOAsync extends Async>, EIOMonadDefer {

  EIOAsync INSTANCE = new EIOAsync() {};
  
  @Override
  default  EIO asyncF(Function1>, Kind, Unit>> consumer) {
    return EIO.cancellable(cb -> consumer.andThen(EIOOf::narrowK).apply(e -> cb.accept(Try.success(e.toEither()))));
  }
}

interface EIOConcurrent extends EIOAsync, Concurrent> {
  
  static EIOConcurrent instance(Executor executor) {
    return () -> executor;
  }
  
  Executor executor();
  
  @Override
  default  EIO, B>>, Tuple2, A>, B>>> racePair(
    Kind, ? extends A> fa, Kind, ? extends B> fb) {
    return EIO.racePair(executor(), fa, fb);
  }

  @Override
  default  EIO, A>> fork(Kind, ? extends A> value) {
    // TODO Auto-generated method stub
    return null;
  }
}

interface EIORuntime extends Runtime> {
  
  @SuppressWarnings("rawtypes")
  EIORuntime INSTANCE = new EIORuntime() {};

  @Override
  default  T run(Kind, T> value) {
    return value.fix(toEIO()).safeRunSync().getRight();
  }
  
  @Override
  default  Sequence run(Sequence, T>> values) {
    return run(EIO.traverse(values.map(EIOOf::narrowK)));
  }

  @Override
  default  Future parRun(Kind, T> value, Executor executor) {
    return value.fix(toEIO()).runAsync().map(Either::get);
  }
  
  @Override
  default  Future> parRun(Sequence, T>> values, Executor executor) {
    return parRun(EIO.traverse(values.map(EIOOf::narrowK)), executor);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy