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

fj.data.State Maven / Gradle / Ivy

Go to download

Functional Java is an open source library that supports closures for the Java programming language

There is a newer version: 5.0
Show newest version
package fj.data;

import fj.F;
import fj.P2;
import fj.Unit;
import fj.control.Trampoline;

import static fj.P.lazy;
import static fj.P.p;
import static fj.control.Trampoline.suspend;
import static fj.data.List.cons;

/**
 * Created by MarkPerry on 7/07/2014.
 */
public final class State {

  public static  State unit(F> runF) {
    return new State<>(s -> Trampoline.pure(runF.f(s)));
  }

  public static  State init() {
    return unit(s -> dup(s));
  }

  public static  State units(F f) {
    return unit(s -> dup(f.f(s)));
  }

  private static  P2 dup(S s) {
    return p(s, s);
  }

  public static  State constant(A a) {
    return unit(s -> p(s, a));
  }

  public static  State gets(F f) {
    return unit(s -> p(s, f.f(s)));
  }

  public static  State put(S s) {
    return unit(ignoredS -> p(s, Unit.unit()));
  }

  public static  State modify(F f) {
    return unit(s -> p(f.f(s), Unit.unit()));
  }

  public static  State flatMap(State ts, F> f) {
    return ts.flatMap(f);
  }

  /**
   * Evaluate each action in the sequence from left to right, and collect the results.
   */
  public static  State> sequence(List> list) {
    return list
        .foldLeft(
            (acc, ts) -> acc.flatMap(as -> ts.map(a -> cons(a, as))),
            State.>constant(List.nil()))
        .map(as -> as.reverse());
  }

  /**
   * Map each element of a structure to an action, evaluate these actions from left to right
   * and collect the results.
   */
  public static  State> traverse(List list, F> f) {
    return list
        .foldLeft(
            (acc, a) -> acc.flatMap(bs -> f.f(a).map(b -> cons(b, bs))),
            State.>constant(List.nil()))
        .map(bs -> bs.reverse());
  }

  private static  State suspended(F>> runF) {
    return new State<>(s -> suspend(lazy(() -> runF.f(s))));
  }

  private final F>> runF;

  private State(F>> runF) {
    this.runF = runF;
  }

  public P2 run(S s) {
    return runF.f(s).run();
  }

  public A eval(S s) {
    return run(s)._2();
  }

  public S exec(S s) {
    return run(s)._1();
  }

  public State gets() {
    return mapState(result -> p(result._1(), result._1()));
  }

  public  State map(F f) {
    return mapState(result -> p(result._1(), f.f(result._2())));
  }

  public  State mapState(F, P2> f) {
    return suspended(s -> runF.f(s).map(result -> f.f(result)));
  }

  public State withs(F f) {
    return suspended(s -> runF.f(f.f(s)));
  }

  public  State flatMap(F> f) {
    return suspended(s -> runF.f(s).bind(result -> Trampoline.pure(f.f(result._2()).run(result._1()))));
  }

}