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

com.github.tonivade.purefun.instances.UIOInstances 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.UIOOf.toUIO;
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.UIO;
import com.github.tonivade.purefun.effect.UIOOf;
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.Console;
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;

public interface UIOInstances {

  static Functor functor() {
    return UIOFunctor.INSTANCE;
  }

  static Applicative applicative() {
    return UIOApplicative.INSTANCE;
  }

  static Monad monad() {
    return UIOMonad.INSTANCE;
  }

  static MonadError monadError() {
    return UIOMonadError.INSTANCE;
  }

  static MonadThrow monadThrow() {
    return UIOMonadThrow.INSTANCE;
  }

  static MonadDefer monadDefer() {
    return UIOMonadDefer.INSTANCE;
  }

  static Async async() {
    return UIOAsync.INSTANCE;
  }

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

  static Concurrent concurrent(Executor executor) {
    return UIOConcurrent.instance(executor);
  }
  
  static Runtime runtime() {
    return UIORuntime.INSTANCE;
  }
  
  static Console console() {
    return UIOConsole.INSTANCE;
  }
}

interface UIOFunctor extends Functor {

  UIOFunctor INSTANCE = new UIOFunctor() {};

  @Override
  default  UIO map(Kind value, Function1 map) {
    return UIOOf.narrowK(value).map(map);
  }
}

interface UIOPure extends Applicative {

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

interface UIOApplicative extends UIOPure {

  UIOApplicative INSTANCE = new UIOApplicative() {};

  @Override
  default  UIO ap(Kind value, 
      Kind> apply) {
    return value.fix(UIOOf::narrowK).ap(apply.fix(UIOOf::narrowK));
  }
}

interface UIOMonad extends UIOPure, Monad {

  UIOMonad INSTANCE = new UIOMonad() {};

  @Override
  default  UIO flatMap(Kind value, 
      Function1> map) {
    return value.fix(toUIO()).flatMap(map.andThen(UIOOf::narrowK));
  }
}

interface UIOMonadError extends UIOMonad, MonadError {

  UIOMonadError INSTANCE = new UIOMonadError() {};

  @Override
  default  UIO raiseError(Throwable error) {
    return UIO.raiseError(error);
  }

  @Override
  default  UIO handleErrorWith(
      Kind value,
      Function1> handler) {
    Function1> mapError = handler.andThen(UIOOf::narrowK);
    Function1> map = UIO::pure;
    UIO uio = UIOOf.narrowK(value);
    return uio.redeemWith(mapError, map);
  }
}

interface UIOMonadThrow extends UIOMonadError, MonadThrow {

  UIOMonadThrow INSTANCE = new UIOMonadThrow() {};
}

interface UIODefer extends Defer {

  @Override
  default  UIO
          defer(Producer> defer) {
    return UIO.defer(defer::get);
  }
}

interface UIOBracket extends UIOMonadError, Bracket {

  @Override
  default  UIO
          bracket(Kind acquire,
                  Function1> use,
                  Function1> release) {
    return UIO.bracket(acquire, use, release);
  }
}

interface UIOMonadDefer
    extends MonadDefer, UIODefer, UIOBracket {

  UIOMonadDefer INSTANCE = new UIOMonadDefer() {};

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

interface UIOAsync extends Async, UIOMonadDefer {

  UIOAsync INSTANCE = new UIOAsync() {};
  
  @Override
  default  UIO asyncF(Function1>, Kind> consumer) {
    return UIO.cancellable(consumer.andThen(UIOOf::narrowK));
  }
}

interface UIOConcurrent extends Concurrent, UIOAsync {
  
  static UIOConcurrent instance(Executor executor) {
    return () -> executor;
  }
  
  Executor executor();
  
  @Override
  default  UIO>, Tuple2, B>>> racePair(Kind fa, Kind fb) {
    return UIO.racePair(executor(), fa, fb);
  }
  
  @Override
  default  UIO> fork(Kind value) {
    UIO fix = value.fix(UIOOf::narrowK);
    return fix.fork();
  }
}

final class UIOConsole implements Console {

  public static final UIOConsole INSTANCE = new UIOConsole();

  private final SystemConsole console = new SystemConsole();

  @Override
  public UIO readln() {
    return UIO.task(console::readln);
  }

  @Override
  public UIO println(String text) {
    return UIO.exec(() -> console.println(text));
  }
}

interface UIORuntime extends Runtime {
  
  UIORuntime INSTANCE = new UIORuntime() {};

  @Override
  default  T run(Kind value) {
    return value.fix(toUIO()).unsafeRunSync();
  }
  
  @Override
  default  Sequence run(Sequence> values) {
    return run(UIO.traverse(values.map(UIOOf::narrowK)));
  }

  @Override
  default  Future parRun(Kind value, Executor executor) {
    return value.fix(toUIO()).runAsync();
  }
  
  @Override
  default  Future> parRun(Sequence> values, Executor executor) {
    return parRun(UIO.traverse(values.map(UIOOf::narrowK)), executor);
  }
}