/** * Provides a stream of the elements of the tree at each level, in level order. * * @return The elements of the tree at each level. */ public Stream<Stream<A>> levels() { final F<Stream<Tree<A>>, Stream<Tree<A>>> flatSubForests = Stream.<Tree<A>, Tree<A>>bind_() .f(compose(P1.<Stream<Tree<A>>>__1(), Tree.<A>subForest_())); final F<Stream<Tree<A>>, Stream<A>> roots = Stream.<Tree<A>, A>map_().f(Tree.<A>root_()); return iterateWhile(flatSubForests, Stream.<Tree<A>>isNotEmpty_(), single(this)).map(roots); }
/** * Folds a Tree<A> into a Tree<B> by applying the function f from the bottom of the Tree to the * top * * @param t A tree to fold from the bottom to the top. * @param f A function transforming the current node and a stream of already transformed nodes * (its children) into a new node * @return The folded tree */ public static <A, B> Tree<B> bottomUp(Tree<A> t, final F<P2<A, Stream<B>>, B> f) { final F<Tree<A>, Tree<B>> recursiveCall = a -> bottomUp(a, f); final Stream<Tree<B>> tbs = t.subForest()._1().map(recursiveCall); return node(f.f(P.p(t.root(), tbs.map(Tree.getRoot()))), tbs); }
/** * Maps the given function over this tree. * * @param f The function to map over this tree. * @return The new Tree after the function has been applied to each element in this Tree. */ public <B> Tree<B> fmap(final F<A, B> f) { return node( f.f(root()), subForest().map(Stream.<Tree<A>, Tree<B>>map_().f(Tree.<A, B>fmap_().f(f)))); }