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

com.github.tonivade.purefun.instances.IOInstances Maven / Gradle / Ivy

/*
 * Copyright (c) 2018-2019, Antonio Gabriel Muñoz Conejo 
 * Distributed under the terms of the MIT License
 */
package com.github.tonivade.purefun.instances;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UncheckedIOException;

import com.github.tonivade.purefun.Consumer1;
import com.github.tonivade.purefun.Function1;
import com.github.tonivade.purefun.Higher1;
import com.github.tonivade.purefun.Instance;
import com.github.tonivade.purefun.Producer;
import com.github.tonivade.purefun.Unit;
import com.github.tonivade.purefun.monad.IO;
import com.github.tonivade.purefun.typeclasses.Comonad;
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.Reference;

public interface IOInstances {

  static Functor functor() {
    return new IOFunctor() {};
  }

  static Monad monad() {
    return new IOMonad() {};
  }

  static Comonad comonad() {
    return new IOComonad() {};
  }

  static Defer defer() {
    return new IODefer() {};
  }

  static MonadError monadError() {
    return new IOMonadError() {};
  }

  static MonadDefer monadDefer() {
    return new IOMonadDefer() {};
  }

  static  Reference ref(A value) {
    return Reference.of(monadDefer(), value);
  }

  static Console console() {
    return new ConsoleIO();
  }
}

@Instance
interface IOFunctor extends Functor {

  @Override
  default  IO map(Higher1 value, Function1 map) {
    return IO.narrowK(value).map(map);
  }
}

@Instance
interface IOComonad extends IOFunctor, Comonad {

  @Override
  default  Higher1 coflatMap(Higher1 value, Function1, B> map) {
    return IO.task(() -> map.apply(value));
  }

  @Override
  default  A extract(Higher1 value) {
    return IO.narrowK(value).unsafeRunSync();
  }
}

@Instance
interface IOMonad extends Monad {

  @Override
  default  IO pure(T value) {
    return IO.pure(value);
  }

  @Override
  default  IO flatMap(Higher1 value, Function1> map) {
    return IO.narrowK(value).flatMap(map.andThen(IO::narrowK));
  }
}

@Instance
interface IOMonadError extends MonadError, IOMonad {

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

  @Override
  default  IO handleErrorWith(Higher1 value, Function1> handler) {
    return IO.narrowK(value).redeemWith(handler.andThen(IO::narrowK), this::pure);
  }
}

@Instance
interface IODefer extends Defer {

  @Override
  default  IO defer(Producer> defer) {
    return IO.suspend(defer.andThen(IO::narrowK));
  }
}

@Instance
interface IOMonadDefer extends MonadDefer, IOMonadError, IODefer {

  @Override
  default  IO bracket(Higher1 acquire, Function1> use, Consumer1 release) {
    return IO.bracket(IO.narrowK(acquire), use.andThen(IO::narrowK), release::accept);
  }
}

@Instance
final class ConsoleIO implements Console {

  private final SystemConsole console = new SystemConsole();

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

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

final class SystemConsole {

  void println(String message) {
    writer().println(message);
  }

  String readln() {
    try {
      return reader().readLine();
    } catch (IOException e) {
      throw new UncheckedIOException(e);
    }
  }

  private BufferedReader reader() {
    return new BufferedReader(new InputStreamReader(System.in));
  }

  private PrintWriter writer() {
    return new PrintWriter(System.out, true);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy