fj.data.fingertrees.Deep 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.fingertrees;
import fj.*;
import fj.data.Option;
import fj.data.vector.V2;
import fj.data.vector.V3;
import fj.data.vector.V4;
import static fj.Function.constant;
import static fj.data.List.list;
import static fj.Function.flip;
/**
* A finger tree with 1-4-digits on the left and right, and a finger tree of 2-3-nodes in the middle.
*/
public final class Deep extends FingerTree {
private final V v;
private final Digit prefix;
private final FingerTree> middle;
private final Digit suffix;
Deep(final Measured m, final V v, final Digit prefix,
final FingerTree> middle,
final Digit suffix) {
super(m);
this.v = v;
this.prefix = prefix;
this.middle = middle;
this.suffix = suffix;
}
/**
* Returns the first few elements of this tree.
*
* @return the first few elements of this tree.
*/
public Digit prefix() {
return prefix;
}
/**
* Returns a finger tree of the inner nodes of this tree.
*
* @return a finger tree of the inner nodes of this tree.
*/
public FingerTree> middle() {
return middle;
}
/**
* Returns the last few elements of this tree.
*
* @return the last few elements of this tree.
*/
public Digit suffix() {
return suffix;
}
@Override public B foldRight(final F> aff, final B z) {
return prefix.foldRight(aff, middle.foldRight(flip(Node.foldRight_(aff)), suffix.foldRight(aff, z)));
}
@Override public A reduceRight(final F> aff) {
return prefix.foldRight(aff, middle.foldRight(flip(Node.foldRight_(aff)), suffix.reduceRight(aff)));
}
@Override public B foldLeft(final F> bff, final B z) {
return suffix.foldLeft(bff, middle.foldLeft(Node.foldLeft_(bff), prefix.foldLeft(bff, z)));
}
@Override public A reduceLeft(final F> aff) {
return suffix.foldLeft(aff, middle.foldLeft(Node.foldLeft_(aff), prefix.reduceLeft(aff)));
}
@Override public FingerTree map(final F abf, final Measured m) {
return new Deep(m, v, prefix.map(abf, m), middle.map(Node.liftM(abf, m), m.nodeMeasured()),
suffix.map(abf, m));
}
/**
* Returns the sum of the measurements of this tree's elements, according to the monoid.
*
* @return the sum of the measurements of this tree's elements, according to the monoid.
*/
public V measure() {
return v;
}
/**
* Pattern matching on the tree. Matches the function on the Deep tree.
*/
@Override public B match(final F, B> empty, final F, B> single,
final F, B> deep) {
return deep.f(this);
}
@Override public FingerTree cons(final A a) {
final Measured m = measured();
final V measure = m.sum(m.measure(a), v);
final MakeTree mk = mkTree(m);
return prefix.match(
one -> new Deep<>(m, measure, mk.two(a, one.value()), middle, suffix),
two -> new Deep<>(m, measure, mk.three(a, two.values()._1(), two.values()._2()), middle, suffix),
three -> new Deep<>(m, measure, mk.four(a, three.values()._1(), three.values()._2(), three.values()._3()), middle, suffix),
four -> new Deep<>(m, measure, mk.two(a, four.values()._1()), middle.cons(mk.node3(four.values()._2(), four.values()._3(), four.values()._4())), suffix));
}
public FingerTree snoc(final A a) {
final Measured m = measured();
final V measure = m.sum(m.measure(a), v);
final MakeTree mk = mkTree(m);
return suffix.match(
one -> new Deep<>(m, measure, prefix, middle, mk.two(one.value(), a)),
two -> new Deep<>(m, measure, prefix, middle, mk.three(two.values()._1(), two.values()._2(), a)),
three -> new Deep<>(m, measure, prefix, middle, mk.four(three.values()._1(), three.values()._2(), three.values()._3(), a)),
four -> new Deep<>(m, measure, prefix, middle.snoc(mk.node3(four.values()._1(), four.values()._2(), four.values()._3())), mk.two(four.values()._4(), a)));
}
@Override public A head() {
return prefix.match(
One::value,
two -> two.values()._1(),
three -> three.values()._1(),
four -> four.values()._1());
}
@Override public A last() {
return suffix.match(
One::value,
two -> two.values()._2(),
three -> three.values()._3(),
four -> four.values()._4());
}
private static final FingerTree deepL(final Measured measured, final Option> lOpt, final FingerTree> m, final Digit r) {
return lOpt.option(
P.lazy(() -> m.isEmpty() ? r.toTree() : mkTree(measured).deep(m.head().toDigit(), m.tail(), r)),
(F, FingerTree>) l -> mkTree(measured).deep(l, m, r)
);
}
private static final FingerTree deepR(final Measured measured, final Option> rOpt, final FingerTree> m, final Digit l) {
return rOpt.option(
P.lazy(() -> m.isEmpty() ? l.toTree() : mkTree(measured).deep(l, m.init(), m.last().toDigit())),
(F, FingerTree>) r -> mkTree(measured).deep(l, m, r)
);
}
@Override public FingerTree tail() { return deepL(measured(), prefix.tail(), middle, suffix); }
@Override public FingerTree init() { return deepR(measured(), suffix.init(), middle, prefix); }
@Override public FingerTree append(final FingerTree t) {
final Measured m = measured();
return t.match(
constant(this),
single -> snoc(single.value()),
deep -> new Deep<>(m, m.sum(measure(), deep.measure()), prefix,
addDigits0(m, middle, suffix, deep.prefix, deep.middle), deep.suffix));
}
@Override P3, A, FingerTree> split1(final F predicate, final V acc) {
final Measured m = measured();
final V accL = m.sum(acc, prefix.measure());
if (predicate.f(accL)) {
final P3