package fj.data.fingertrees;
import fj.data.vector.V2;
import fj.data.vector.V3;
import static fj.data.vector.V.v;
/**
* A builder of trees and tree components, supplied with a particular monoid and measuring function.
*/
public final class MakeTree<V, A> {
private final Measured<V, A> m;
private final Empty<V, A> empty;
MakeTree(final Measured<V, A> m) {
this.m = m;
this.empty = new Empty<>(m);
}
// Tree constructors
/**
* Constructs an empty tree.
*
* @return The empty tree.
*/
public FingerTree<V, A> empty() {
return empty;
}
/**
* Constructs a singleton tree.
*
* @param a A single element for the tree.
* @return A tree with the given value as the single element.
*/
public FingerTree<V, A> single(final A a) {
return new Single<>(m, a);
}
/**
* Constructs a deep tree. This structure consists of two digits, of 1 to 4 elements each, on the left and right,
* with the rest of the tree in the middle.
*
* @param prefix The leftmost elements of the tree.
* @param middle The subtree, which is a Finger Tree of 2-3 nodes.
* @param suffix The rightmost elements of the tree.
* @return A new finger tree with the given prefix, suffix, and middle.
*/
public FingerTree<V, A> deep(final Digit<V, A> prefix, final FingerTree<V, Node<V, A>> middle,
final Digit<V, A> suffix) {
return deep(m.sum(prefix.measure(), m.sum(middle.measure(), suffix.measure())), prefix, middle, suffix);
}
/**
* Constructs a deep tree with the given annotation value.
*
* @param v The value with which to annotate this tree.
* @param prefix The leftmost elements of the tree.
* @param middle The subtree, which is a Finger Tree of 2-3 nodes.
* @param suffix The rightmost elements of the tree.
* @return A new finger tree with the given prefix, suffix, and middle, and annotated with the given value.
*/
public FingerTree<V, A> deep(final V v, final Digit<V, A> prefix, final FingerTree<V, Node<V, A>> middle,
final Digit<V, A> suffix) {
return new Deep<>(m, v, prefix, middle, suffix);
}
// Digit constructors
/**
* A digit of one element.
*
* @param a The element of the digit.
* @return A digit of the given element.
*/
public One<V, A> one(final A a) {
return new One<>(m, a);
}
/**
* A digit of two elements.
*
* @param a The first element of the digit.
* @param b The second element of the digit.
* @return A digit of the given elements.
*/
public Two<V, A> two(final A a, final A b) {
return new Two<>(m, v(a, b));
}
/**
* A digit of three elements.
*
* @param a The first element of the digit.
* @param b The second element of the digit.
* @param c The third element of the digit.
* @return A digit of the given elements.
*/
public Three<V, A> three(final A a, final A b, final A c) {
return new Three<>(m, v(a, b, c));
}
/**
* A digit of four elements.
*
* @param a The first element of the digit.
* @param b The second element of the digit.
* @param c The third element of the digit.
* @param d The fifth element of the digit.
* @return A digit of the given elements.
*/
public Four<V, A> four(final A a, final A b, final A c, final A d) {
return new Four<>(m, v(a, b, c, d));
}
// Node constructors
/**
* A binary tree node.
*
* @param a The left child of the node.
* @param b The right child of the node.
* @return A new binary tree node.
*/
public Node2<V, A> node2(final A a, final A b) {
return new Node2<>(m, v(a, b));
}
/**
* A trinary tree node.
*
* @param a The left child of the node.
* @param b The middle child of the node.
* @param c The right child of the node.
* @return A new trinary tree node.
*/
public Node3<V, A> node3(final A a, final A b, final A c) {
return new Node3<>(m, v(a, b, c));
}
/**
* A binary tree node
*
* @param v A vector of the node's elements.
* @return A new binary tree node.
*/
public Node2<V, A> node2(final V2<A> v) {
return new Node2<>(m, v);
}
/**
* A trinary tree node
*
* @param v A vector of the node's elements.
* @return A new trinary tree node.
*/
public Node3<V, A> node3(final V3<A> v) {
return new Node3<>(m, v);
}
}