Mercurial > hg > Members > tatsuki > functionaljava-master > core
comparison src/main/java/fj/data/NonEmptyList.java @ 0:fe80c1edf1be
add getLoop
author | tatsuki |
---|---|
date | Fri, 20 Mar 2015 21:04:03 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:fe80c1edf1be |
---|---|
1 package fj.data; | |
2 | |
3 import fj.F; | |
4 import fj.F1Functions; | |
5 import fj.function.Effect1; | |
6 | |
7 import static fj.data.Option.some; | |
8 import static fj.data.Option.somes; | |
9 | |
10 import java.util.Collection; | |
11 import java.util.Iterator; | |
12 | |
13 /** | |
14 * Provides an in-memory, immutable, singly linked list with total <code>head</code> and <code>tail</code>. | |
15 * | |
16 * @version %build.number% | |
17 */ | |
18 public final class NonEmptyList<A> implements Iterable<A> { | |
19 /** | |
20 * Returns an iterator for this non-empty list. This method exists to permit the use in a <code>for</code>-each loop. | |
21 * | |
22 * @return A iterator for this non-empty list. | |
23 */ | |
24 | |
25 public Iterator<A> iterator() { | |
26 return toCollection().iterator(); | |
27 } | |
28 | |
29 /** | |
30 * The first element of this linked list. | |
31 */ | |
32 @SuppressWarnings({"PublicField", "ClassEscapesDefinedScope"}) | |
33 public final A head; | |
34 | |
35 /** | |
36 * This list without the first element. | |
37 */ | |
38 @SuppressWarnings({"PublicField"}) | |
39 public final List<A> tail; | |
40 | |
41 private NonEmptyList(final A head, final List<A> tail) { | |
42 this.head = head; | |
43 this.tail = tail; | |
44 } | |
45 | |
46 /** | |
47 * Prepend the given value to this list. | |
48 * | |
49 * @param a The value to prepend. | |
50 * @return A non-empty list with an extra element. | |
51 */ | |
52 public NonEmptyList<A> cons(final A a) { | |
53 return nel(a, tail.cons(head)); | |
54 } | |
55 | |
56 /** | |
57 * Appends the given list to this list. | |
58 * | |
59 * @param as The list to append. | |
60 * @return A new list with the given list appended. | |
61 */ | |
62 public NonEmptyList<A> append(final NonEmptyList<A> as) { | |
63 final List.Buffer<A> b = new List.Buffer<A>(); | |
64 b.append(tail); | |
65 b.snoc(as.head); | |
66 b.append(as.tail); | |
67 final List<A> bb = b.toList(); | |
68 return nel(head, bb); | |
69 } | |
70 | |
71 /** | |
72 * Maps the given function across this list. | |
73 * | |
74 * @param f The function to map across this list. | |
75 * @return A new list after the given function has been applied to each element. | |
76 */ | |
77 public <B> NonEmptyList<B> map(final F<A, B> f) { | |
78 return nel(f.f(head), tail.map(f)); | |
79 } | |
80 | |
81 /** | |
82 * Binds the given function across each element of this list with a final join. | |
83 * | |
84 * @param f The function to apply to each element of this list. | |
85 * @return A new list after performing the map, then final join. | |
86 */ | |
87 public <B> NonEmptyList<B> bind(final F<A, NonEmptyList<B>> f) { | |
88 final List.Buffer<B> b = new List.Buffer<B>(); | |
89 final NonEmptyList<B> p = f.f(head); | |
90 b.snoc(p.head); | |
91 b.append(p.tail); | |
92 tail.foreachDoEffect(new Effect1<A>() { | |
93 public void f(final A a) { | |
94 final NonEmptyList<B> p = f.f(a); | |
95 b.snoc(p.head); | |
96 b.append(p.tail); | |
97 } | |
98 }); | |
99 final List<B> bb = b.toList(); | |
100 return nel(bb.head(), bb.tail()); | |
101 } | |
102 | |
103 /** | |
104 * Returns a NonEmptyList of the sublists of this list. | |
105 * | |
106 * @return a NonEmptyList of the sublists of this list. | |
107 */ | |
108 public NonEmptyList<NonEmptyList<A>> sublists() { | |
109 return fromList( | |
110 somes(toList().toStream().substreams() | |
111 .map(F1Functions.o(new F<List<A>, Option<NonEmptyList<A>>>() { | |
112 public Option<NonEmptyList<A>> f(final List<A> list) { | |
113 return fromList(list); | |
114 } | |
115 }, Conversions.<A>Stream_List())).toList())).some(); | |
116 } | |
117 | |
118 /** | |
119 * Returns a NonEmptyList of the tails of this list. A list is considered a tail of itself for the purpose of this | |
120 * function (Comonad pattern). | |
121 * | |
122 * @return A NonEmptyList of the tails of this list. | |
123 */ | |
124 public NonEmptyList<NonEmptyList<A>> tails() { | |
125 return fromList(somes(toList().tails().map(new F<List<A>, Option<NonEmptyList<A>>>() { | |
126 public Option<NonEmptyList<A>> f(final List<A> list) { | |
127 return fromList(list); | |
128 } | |
129 }))).some(); | |
130 } | |
131 | |
132 /** | |
133 * Maps the given function across the tails of this list (comonad pattern). | |
134 * | |
135 * @param f The function to map across the tails of this list. | |
136 * @return The results of applying the given function to the tails of this list, as a NonEmptyList. | |
137 */ | |
138 public <B> NonEmptyList<B> mapTails(final F<NonEmptyList<A>, B> f) { | |
139 return tails().map(f); | |
140 } | |
141 | |
142 /** | |
143 * Returns a <code>List</code> projection of this list. | |
144 * | |
145 * @return A <code>List</code> projection of this list. | |
146 */ | |
147 public List<A> toList() { | |
148 return tail.cons(head); | |
149 } | |
150 | |
151 /** | |
152 * Projects an immutable collection of this non-empty list. | |
153 * | |
154 * @return An immutable collection of this non-empty list. | |
155 */ | |
156 public Collection<A> toCollection() { | |
157 return toList().toCollection(); | |
158 } | |
159 | |
160 /** | |
161 * Returns a function that takes a non-empty list to a list. | |
162 * | |
163 * @return A function that takes a non-empty list to a list. | |
164 */ | |
165 public static <A> F<NonEmptyList<A>, List<A>> toList_() { | |
166 return new F<NonEmptyList<A>, List<A>>() { | |
167 public List<A> f(final NonEmptyList<A> as) { | |
168 return as.toList(); | |
169 } | |
170 }; | |
171 } | |
172 | |
173 /** | |
174 * Return a non-empty list with the given head and tail. | |
175 * | |
176 * @param head The first element of the new list. | |
177 * @param tail The remaining elements of the new list. | |
178 * @return A non-empty list with the given head and tail. | |
179 */ | |
180 public static <A> NonEmptyList<A> nel(final A head, final List<A> tail) { | |
181 return new NonEmptyList<A>(head, tail); | |
182 } | |
183 | |
184 /** | |
185 * Return a non-empty list with the given value. | |
186 * | |
187 * @param head The value in the non-empty list. | |
188 * @return A non-empty list with the given value. | |
189 */ | |
190 public static <A> NonEmptyList<A> nel(final A head) { | |
191 return nel(head, List.<A>nil()); | |
192 } | |
193 | |
194 /** | |
195 * Returns a function that puts an element into a non-empty list. | |
196 * | |
197 * @return A function that puts an element into a non-empty list. | |
198 */ | |
199 public static <A> F<A, NonEmptyList<A>> nel() { | |
200 return new F<A, NonEmptyList<A>>() { | |
201 public NonEmptyList<A> f(final A a) { | |
202 return nel(a); | |
203 } | |
204 }; | |
205 } | |
206 | |
207 /** | |
208 * Returns a potential non-empty list from the given list. A non-value is returned if the given list is empty. | |
209 * | |
210 * @param as The list to construct a potential non-empty list with. | |
211 * @return A potential non-empty list from the given list. | |
212 */ | |
213 public static <A> Option<NonEmptyList<A>> fromList(final List<A> as) { | |
214 return as.isEmpty() ? | |
215 Option.<NonEmptyList<A>>none() : | |
216 some(nel(as.head(), as.tail())); | |
217 } | |
218 } |