fj.data.State Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of functionaljava Show documentation
Show all versions of functionaljava Show documentation
Functional Java is an open source library that supports closures for the Java programming language
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()))));
}
}