
fj.data.State Maven / Gradle / Ivy
package fj.data;
import fj.F;
import fj.P2;
import fj.Unit;
import fj.control.Trampoline;
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(() -> 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()))));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy