annotate src/main/java/fj/data/Tree.java @ 0:fe80c1edf1be

add getLoop
author tatsuki
date Fri, 20 Mar 2015 21:04:03 +0900
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
1 package fj.data;
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
2
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
3 import fj.F;
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
4 import fj.F2;
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
5 import fj.F2Functions;
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
6 import fj.P;
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
7 import fj.P1;
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
8 import fj.P2;
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
9 import static fj.Function.*;
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
10 import static fj.data.Stream.*;
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
11 import fj.Monoid;
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
12 import fj.Show;
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
13
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
14 import java.util.Collection;
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
15 import java.util.Iterator;
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
16
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
17 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
18 * Provides a lazy, immutable, non-empty, multi-way tree (a rose tree).
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
19 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
20 * @version %build.number%
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
21 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
22 public final class Tree<A> implements Iterable<A> {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
23 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
24 * Returns an iterator for this tree. This method exists to permit the use in a <code>for</code>-each loop.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
25 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
26 * @return A iterator for this tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
27 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
28 public Iterator<A> iterator() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
29 return flatten().iterator();
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
30 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
31
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
32 private final A root;
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
33 private final P1<Stream<Tree<A>>> subForest;
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
34
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
35 private Tree(final A root, final P1<Stream<Tree<A>>> subForest) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
36 this.root = root;
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
37 this.subForest = subForest;
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
38 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
39
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
40 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
41 * Creates a nullary tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
42 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
43 * @param root The root element of the tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
44 * @return A nullary tree with the root element in it.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
45 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
46 public static <A> Tree<A> leaf(final A root) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
47 return node(root, Stream.<Tree<A>>nil());
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
48 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
49
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
50 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
51 * Creates a new tree given a root and a (potentially infinite) subforest.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
52 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
53 * @param root The root element of the tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
54 * @param forest A stream of the tree's subtrees.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
55 * @return A newly sprouted tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
56 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
57 public static <A> Tree<A> node(final A root, final P1<Stream<Tree<A>>> forest) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
58 return new Tree<A>(root, forest);
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
59 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
60
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
61 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
62 * Creates a new tree given a root and a (potentially infinite) subforest.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
63 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
64 * @param root The root element of the tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
65 * @param forest A stream of the tree's subtrees.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
66 * @return A newly sprouted tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
67 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
68 public static <A> Tree<A> node(final A root, final Stream<Tree<A>> forest) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
69 return new Tree<A>(root, P.p(forest));
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
70 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
71
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
72 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
73 * Creates a new n-ary given a root and a subforest of length n.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
74 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
75 * @param root The root element of the tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
76 * @param forest A list of the tree's subtrees.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
77 * @return A newly sprouted tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
78 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
79 public static <A> Tree<A> node(final A root, final List<Tree<A>> forest) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
80 return node(root, forest.toStream());
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
81 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
82
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
83 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
84 * First-class constructor of trees.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
85 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
86 * @return A function that constructs an n-ary tree given a root and a subforest or length n.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
87 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
88 public static <A> F<A, F<P1<Stream<Tree<A>>>, Tree<A>>> node() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
89 return curry(new F2<A, P1<Stream<Tree<A>>>, Tree<A>>() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
90 public Tree<A> f(final A a, final P1<Stream<Tree<A>>> p1) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
91 return node(a, p1);
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
92 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
93 });
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
94 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
95
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
96 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
97 * Returns the root element of the tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
98 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
99 * @return The root element of the tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
100 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
101 public A root() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
102 return root;
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
103 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
104
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
105 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
106 * Returns a stream of the tree's subtrees.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
107 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
108 * @return A stream of the tree's subtrees.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
109 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
110 public P1<Stream<Tree<A>>> subForest() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
111 return subForest;
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
112 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
113
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
114 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
115 * Provides a transformation from a tree to its root.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
116 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
117 * @return A transformation from a tree to its root.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
118 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
119 public static <A> F<Tree<A>, A> root_() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
120 return new F<Tree<A>, A>() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
121 public A f(final Tree<A> a) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
122 return a.root();
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
123 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
124 };
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
125 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
126
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
127 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
128 * Provides a transformation from a tree to its subforest.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
129 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
130 * @return A transformation from a tree to its subforest.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
131 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
132 public static <A> F<Tree<A>, P1<Stream<Tree<A>>>> subForest_() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
133 return new F<Tree<A>, P1<Stream<Tree<A>>>>() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
134 public P1<Stream<Tree<A>>> f(final Tree<A> a) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
135 return a.subForest();
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
136 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
137 };
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
138 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
139
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
140 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
141 * Puts the elements of the tree into a Stream, in pre-order.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
142 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
143 * @return The elements of the tree in pre-order.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
144 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
145 public Stream<A> flatten() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
146 final F2<Tree<A>, P1<Stream<A>>, Stream<A>> squish = new F2<Tree<A>, P1<Stream<A>>, Stream<A>>() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
147 public Stream<A> f(final Tree<A> t, final P1<Stream<A>> xs) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
148 return cons(t.root(), t.subForest().map(Stream.<Tree<A>, Stream<A>>foldRight().f(F2Functions.curry(this)).f(xs._1())));
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
149 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
150 };
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
151 return squish.f(this, P.p(Stream.<A>nil()));
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
152 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
153
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
154 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
155 * flatten :: Tree a -> [a]
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
156 * flatten t = squish t []
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
157 * where squish (Node x ts) xs = x:Prelude.foldr squish xs ts
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
158 * Puts the elements of the tree into a Stream, in pre-order.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
159 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
160 * @return The elements of the tree in pre-order.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
161 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
162 public static <A> F<Tree<A>, Stream<A>> flatten_() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
163 return new F<Tree<A>, Stream<A>>() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
164 public Stream<A> f(final Tree<A> t) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
165 return t.flatten();
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
166 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
167 };
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
168 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
169
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
170 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
171 * Provides a stream of the elements of the tree at each level, in level order.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
172 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
173 * @return The elements of the tree at each level.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
174 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
175 public Stream<Stream<A>> levels() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
176 final F<Stream<Tree<A>>, Stream<Tree<A>>> flatSubForests =
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
177 Stream.<Tree<A>, Tree<A>>bind_().f(compose(P1.<Stream<Tree<A>>>__1(), Tree.<A>subForest_()));
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
178 final F<Stream<Tree<A>>, Stream<A>> roots = Stream.<Tree<A>, A>map_().f(Tree.<A>root_());
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
179 return iterateWhile(flatSubForests, Stream.<Tree<A>>isNotEmpty_(), single(this)).map(roots);
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
180 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
181
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
182 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
183 * Maps the given function over this tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
184 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
185 * @param f The function to map over this tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
186 * @return The new Tree after the function has been applied to each element in this Tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
187 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
188 public <B> Tree<B> fmap(final F<A, B> f) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
189 return node(f.f(root()), subForest().map(Stream.<Tree<A>, Tree<B>>map_().f(Tree.<A, B>fmap_().f(f))));
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
190 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
191
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
192 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
193 * Provides a transformation to lift any function so that it maps over Trees.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
194 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
195 * @return A transformation to lift any function so that it maps over Trees.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
196 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
197 public static <A, B> F<F<A, B>, F<Tree<A>, Tree<B>>> fmap_() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
198 return new F<F<A, B>, F<Tree<A>, Tree<B>>>() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
199 public F<Tree<A>, Tree<B>> f(final F<A, B> f) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
200 return new F<Tree<A>, Tree<B>>() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
201 public Tree<B> f(final Tree<A> a) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
202 return a.fmap(f);
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
203 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
204 };
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
205 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
206 };
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
207 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
208
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
209 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
210 * Folds this tree using the given monoid.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
211 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
212 * @param f A transformation from this tree's elements, to the monoid.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
213 * @param m The monoid to fold this tree with.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
214 * @return The result of folding the tree with the given monoid.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
215 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
216 public <B> B foldMap(final F<A, B> f, final Monoid<B> m) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
217 return m.sum(f.f(root()), m.sumRight(subForest()._1().map(foldMap_(f, m)).toList()));
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
218 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
219
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
220 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
221 * Projects an immutable collection of this tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
222 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
223 * @return An immutable collection of this tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
224 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
225 public Collection<A> toCollection() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
226 return flatten().toCollection();
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
227 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
228
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
229 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
230 * Provides a function that folds a tree with the given monoid.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
231 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
232 * @param f A transformation from a tree's elements to the monoid.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
233 * @param m A monoid to fold the tree with.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
234 * @return A function that, given a tree, folds it with the given monoid.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
235 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
236 public static <A, B> F<Tree<A>, B> foldMap_(final F<A, B> f, final Monoid<B> m) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
237 return new F<Tree<A>, B>() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
238 public B f(final Tree<A> t) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
239 return t.foldMap(f, m);
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
240 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
241 };
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
242 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
243
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
244 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
245 * Builds a tree from a seed value.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
246 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
247 * @param f A function with which to build the tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
248 * @return A function which, given a seed value, yields a tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
249 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
250 public static <A, B> F<B, Tree<A>> unfoldTree(final F<B, P2<A, P1<Stream<B>>>> f) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
251 return new F<B, Tree<A>>() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
252 public Tree<A> f(final B b) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
253 final P2<A, P1<Stream<B>>> p = f.f(b);
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
254 return node(p._1(), p._2().map(Stream.<B, Tree<A>>map_().f(unfoldTree(f))));
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
255 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
256 };
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
257 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
258
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
259 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
260 * Applies the given function to all subtrees of this tree, returning a tree of the results (comonad pattern).
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
261 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
262 * @param f A function to bind across all the subtrees of this tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
263 * @return A new tree, with the results of applying the given function to each subtree of this tree. The result
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
264 * of applying the function to the entire tree is the root label, and the results of applying to the
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
265 * root's children are labels of the root's subforest, etc.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
266 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
267 public <B> Tree<B> cobind(final F<Tree<A>, B> f) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
268 return unfoldTree(new F<Tree<A>, P2<B, P1<Stream<Tree<A>>>>>() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
269 public P2<B, P1<Stream<Tree<A>>>> f(final Tree<A> t) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
270 return P.p(f.f(t), t.subForest());
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
271 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
272 }).f(this);
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
273 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
274
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
275 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
276 * Expands this tree into a tree of trees, with this tree as the root label, and subtrees as the labels of
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
277 * child nodes (comonad pattern).
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
278 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
279 * @return A tree of trees, with this tree as its root label, and subtrees of this tree as the labels of
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
280 * its child nodes.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
281 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
282 public Tree<Tree<A>> cojoin() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
283 final F<Tree<A>, Tree<A>> id = identity();
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
284 return cobind(id);
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
285 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
286
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
287 private static <A> Stream<String> drawSubTrees(final Show<A> s, final Stream<Tree<A>> ts) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
288 return ts.isEmpty() ? Stream.<String>nil()
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
289 : ts.tail()._1().isEmpty() ? shift("`- ", " ", ts.head().drawTree(s)).cons("|")
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
290 : shift("+- ", "| ", ts.head().drawTree(s))
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
291 .append(drawSubTrees(s, ts.tail()._1()));
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
292 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
293
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
294 private static Stream<String> shift(final String f, final String o, final Stream<String> s) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
295 return Stream.repeat(o).cons(f).zipWith(s, Monoid.stringMonoid.sum());
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
296 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
297
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
298 private Stream<String> drawTree(final Show<A> s) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
299 return drawSubTrees(s, subForest._1()).cons(s.showS(root));
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
300 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
301
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
302 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
303 * Draws a 2-dimensional representation of a tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
304 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
305 * @param s A show instance for the elements of the tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
306 * @return a String showing this tree in two dimensions.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
307 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
308 public String draw(final Show<A> s) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
309 return Monoid.stringMonoid.join(drawTree(s), "\n");
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
310 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
311
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
312 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
313 * Provides a show instance that draws a 2-dimensional representation of a tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
314 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
315 * @param s A show instance for the elements of the tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
316 * @return a show instance that draws a 2-dimensional representation of a tree.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
317 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
318 public static <A> Show<Tree<A>> show2D(final Show<A> s) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
319 return Show.showS(new F<Tree<A>, String>() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
320 public String f(final Tree<A> tree) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
321 return tree.draw(s);
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
322 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
323 });
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
324 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
325
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
326 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
327 * Zips this tree with another, using the given function. The resulting tree is the structural intersection
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
328 * of the two trees.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
329 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
330 * @param bs A tree to zip this tree with.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
331 * @param f A function with which to zip together the two trees.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
332 * @return A new tree of the results of applying the given function over this tree and the given tree, position-wise.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
333 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
334 public <B, C> Tree<C> zipWith(final Tree<B> bs, final F2<A, B, C> f) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
335 return F2Functions.zipTreeM(f).f(this, bs);
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
336 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
337
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
338 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
339 * Zips this tree with another, using the given function. The resulting tree is the structural intersection
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
340 * of the two trees.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
341 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
342 * @param bs A tree to zip this tree with.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
343 * @param f A function with which to zip together the two trees.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
344 * @return A new tree of the results of applying the given function over this tree and the given tree, position-wise.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
345 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
346 public <B, C> Tree<C> zipWith(final Tree<B> bs, final F<A, F<B, C>> f) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
347 return zipWith(bs, uncurryF2(f));
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
348 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
349
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
350 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
351 * Folds a Tree<A> into a Tree<B> by applying the function f from the bottom of the Tree to the top
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
352 *
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
353 * @param t A tree to fold from the bottom to the top.
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
354 * @param f A function transforming the current node and a stream of already transformed nodes (its children) into a new node
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
355 * @return The folded tree
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
356 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
357 public static <A, B> Tree<B> bottomUp(Tree<A> t, final F<P2<A, Stream<B>>, B> f) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
358 final F<Tree<A>, Tree<B>> recursiveCall = new F<Tree<A>, Tree<B>>() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
359 @Override public Tree<B> f(Tree<A> a) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
360 return bottomUp(a, f);
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
361 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
362 };
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
363
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
364 final Stream<Tree<B>> tbs = t.subForest()._1().map(recursiveCall);
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
365 return Tree.node(f.f(P.p(t.root(), tbs.map(Tree.<B> getRoot()))), tbs);
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
366 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
367
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
368 /**
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
369 * @return a function getting the root of a Tree
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
370 */
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
371 private static <A> F<Tree<A>, A> getRoot() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
372 return new F<Tree<A>, A>() {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
373 @Override public A f(Tree<A> a) {
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
374 return a.root();
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
375 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
376 };
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
377 }
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
378
fe80c1edf1be add getLoop
tatsuki
parents:
diff changeset
379 }