Mercurial > hg > Members > tatsuki > functionaljava-master > core
comparison src/main/java/fj/data/hlist/HList.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.hlist; | |
2 | |
3 import fj.F; | |
4 import fj.F2; | |
5 import fj.F3; | |
6 import fj.P; | |
7 import fj.P2; | |
8 import fj.Unit; | |
9 import static fj.Function.compose; | |
10 | |
11 /** | |
12 * Type-safe heterogeneous lists. | |
13 * | |
14 * @param <A> The specific type of the list, as a subtype of HList | |
15 */ | |
16 public abstract class HList<A extends HList<A>> { | |
17 | |
18 HList() { | |
19 } | |
20 | |
21 /** | |
22 * Extends (cons) this list by prepending the given element, returning a new list. | |
23 * | |
24 * @param e an element to prepend to this list. | |
25 * @return a new heterogeneous list, consisting of the given element prepended to this list. | |
26 */ | |
27 public abstract <E> HCons<E, A> extend(E e); | |
28 | |
29 public abstract <E> Apply<Unit, P2<E, A>, HCons<E, A>> extender(); | |
30 | |
31 private static final HNil nil = new HNil(); | |
32 | |
33 /** | |
34 * Returns the empty list. | |
35 * | |
36 * @return the empty list. | |
37 */ | |
38 public static HNil nil() { | |
39 return nil; | |
40 } | |
41 | |
42 /** | |
43 * Returns a heterogeneous list consisting of an element and another list. | |
44 * | |
45 * @param e an element to put in a list. | |
46 * @param l the rest of the list. | |
47 * @return a heterogeneous list consisting of an element and another list. | |
48 */ | |
49 public static <E, L extends HList<L>> HCons<E, L> cons(final E e, final L l) { | |
50 return new HCons<E, L>(e, l); | |
51 } | |
52 | |
53 /** | |
54 * Returns a heterogeneous list consisting of a single element. | |
55 * | |
56 * @param e an element to put in a list | |
57 * @return a heterogeneous list consisting of a single element. | |
58 */ | |
59 public static <E> HCons<E, HNil> single(final E e) { | |
60 return cons(e, nil()); | |
61 } | |
62 | |
63 /** | |
64 * The concatenation of two heterogeneous lists. | |
65 * | |
66 * @param <A> The type of the first list. | |
67 * @param <B> The type of the second list. | |
68 * @param <C> The type of the combined list. | |
69 */ | |
70 public static final class HAppend<A, B, C> { | |
71 private final F2<A, B, C> append; | |
72 | |
73 private HAppend(final F2<A, B, C> f) { | |
74 append = f; | |
75 } | |
76 | |
77 /** | |
78 * Append a given heterogeneous list to another. | |
79 * | |
80 * @param a a heterogeneous list to be appended to. | |
81 * @param b a heterogeneous list to append to another. | |
82 * @return a new heterogeneous list consisting of the second argument appended to the first. | |
83 */ | |
84 public C append(final A a, final B b) { | |
85 return append.f(a, b); | |
86 } | |
87 | |
88 /** | |
89 * Returns a method for concatenating lists to the empty list. | |
90 * | |
91 * @return a method for concatenating lists to the empty list. | |
92 */ | |
93 public static <L extends HList<L>> HAppend<HNil, L, L> append() { | |
94 return new HAppend<HNil, L, L>(new F2<HNil, L, L>() { | |
95 public L f(final HNil hNil, final L l) { | |
96 return l; | |
97 } | |
98 }); | |
99 } | |
100 | |
101 /** | |
102 * Returns a method for appending lists to a nonempty heterogeneous list. | |
103 * | |
104 * @param h a method for appending lists to the tail of the given nonempty list. | |
105 * @return a method for appending lists to a nonempty heterogeneous list. | |
106 */ | |
107 public static <X, A extends HList<A>, B, C extends HList<C>, H extends HAppend<A, B, C>> | |
108 HAppend<HCons<X, A>, B, HCons<X, C>> append(final H h) { | |
109 return new HAppend<HCons<X, A>, B, HCons<X, C>>(new F2<HCons<X, A>, B, HCons<X, C>>() { | |
110 public HCons<X, C> f(final HCons<X, A> c, final B l) { | |
111 return cons(c.head(), h.append(c.tail(), l)); | |
112 } | |
113 }); | |
114 } | |
115 } | |
116 | |
117 /** | |
118 * Type-level function application operators. | |
119 * | |
120 * @param <F$> The type of the function to apply. | |
121 * @param <A> The domain of the function. | |
122 * @param <R> The function's codomain. | |
123 */ | |
124 public abstract static class Apply<F$, A, R> { | |
125 public abstract R apply(F$ f, A a); | |
126 | |
127 /** | |
128 * Function application operator. | |
129 * | |
130 * @return an operator that applies a given function to a given argument. | |
131 */ | |
132 public static <X, Y> Apply<F<X, Y>, X, Y> f() { | |
133 return new Apply<F<X, Y>, X, Y>() { | |
134 public Y apply(final F<X, Y> f, final X x) { | |
135 return f.f(x); | |
136 } | |
137 }; | |
138 } | |
139 | |
140 /** | |
141 * Identity operator | |
142 * | |
143 * @return An operator that returns its second argument no matter which function is being applied. | |
144 */ | |
145 public static <X> Apply<Unit, X, X> id() { | |
146 return new Apply<Unit, X, X>() { | |
147 public X apply(final Unit f, final X x) { | |
148 return x; | |
149 } | |
150 }; | |
151 } | |
152 | |
153 /** | |
154 * A function application operator for function composition. | |
155 * | |
156 * @param <X> The domain. | |
157 * @param <Y> The type through which to compose. | |
158 * @param <Z> The codomain. | |
159 * @return an operator that composes functions. | |
160 */ | |
161 public static <X, Y, Z> Apply<Unit, P2<F<X, Y>, F<Y, Z>>, F<X, Z>> comp() { | |
162 return new Apply<Unit, P2<F<X, Y>, F<Y, Z>>, F<X, Z>>() { | |
163 public F<X, Z> apply(final Unit f, final P2<F<X, Y>, F<Y, Z>> fs) { | |
164 return compose(fs._2(), fs._1()); | |
165 } | |
166 }; | |
167 } | |
168 | |
169 /** | |
170 * An operator for the construction of heterogeneous lists. | |
171 * | |
172 * @return an operator that constructs heterogeneous lists. | |
173 */ | |
174 public static <E, L extends HList<L>> Apply<Unit, P2<E, L>, HCons<E, L>> cons() { | |
175 return new Apply<Unit, P2<E, L>, HCons<E, L>>() { | |
176 public HCons<E, L> apply(final Unit f, final P2<E, L> p) { | |
177 return HList.cons(p._1(), p._2()); | |
178 } | |
179 }; | |
180 } | |
181 | |
182 /** | |
183 * A function application operator for concatenating heterogeneous lists. | |
184 * | |
185 * @param <A> The type of the list to which to append. | |
186 * @param <B> The type of the list to append. | |
187 * @param <C> The type of the concatenated list. | |
188 * @return an operator that concatenates heterogeneous lists. | |
189 */ | |
190 public static <A, B, C> Apply<HAppend<A, B, C>, P2<A, B>, C> append() { | |
191 return new Apply<HAppend<A, B, C>, P2<A, B>, C>() { | |
192 public C apply(final HAppend<A, B, C> f, final P2<A, B> p) { | |
193 return f.append(p._1(), p._2()); | |
194 } | |
195 }; | |
196 } | |
197 } | |
198 | |
199 /** | |
200 * The catamorphism over heterogeneous lists. | |
201 * | |
202 * @param <G> The type of the function with which to fold. | |
203 * @param <V> The type of the value to be substituted for the empty list. | |
204 * @param <L> The type of the heterogeneous list to be folded. | |
205 * @param <R> The return type of the fold. | |
206 */ | |
207 public static final class HFoldr<G, V, L, R> { | |
208 | |
209 private final F3<G, V, L, R> foldRight; | |
210 | |
211 private HFoldr(final F3<G, V, L, R> foldRight) { | |
212 this.foldRight = foldRight; | |
213 } | |
214 | |
215 /** | |
216 * A fold instance for the empty list. | |
217 * | |
218 * @param <G> The type of the function with which to fold. | |
219 * @param <V> The type of value that this fold returns. | |
220 * @return a fold instance for the empty list. | |
221 */ | |
222 public static <G, V> HFoldr<G, V, HNil, V> hFoldr() { | |
223 return new HFoldr<G, V, HNil, V>(new F3<G, V, HNil, V>() { | |
224 public V f(final G f, final V v, final HNil hNil) { | |
225 return v; | |
226 } | |
227 }); | |
228 } | |
229 | |
230 /** | |
231 * A fold instance for a non-empty heterogeneous list | |
232 * | |
233 * @param p An operator that applies a function on the head of the list and the fold of its tail. | |
234 * @param h A fold instance for the tail of the list. | |
235 * @param <E> The type of the head of the list. | |
236 * @param <G> The type of function to apply to the head of the list and the fold of its tail. | |
237 * @param <V> The type of value to substitute for the empty list. | |
238 * @param <L> The type of the tail of the list. | |
239 * @param <R> The type of the fold of the tail of the list. | |
240 * @param <RR> The return type of the fold. | |
241 * @param <H> The type of the fold instance for the tail of the list. | |
242 * @param <PP> The type of the given function application operator. | |
243 * @return A fold instance for a non-empty heterogeneous list. | |
244 */ | |
245 public static <E, G, V, L extends HList<L>, R, RR, | |
246 H extends HFoldr<G, V, L, R>, | |
247 PP extends Apply<G, P2<E, R>, RR>> | |
248 HFoldr<G, V, HCons<E, L>, RR> hFoldr(final PP p, final H h) { | |
249 return new HFoldr<G, V, HCons<E, L>, RR>(new F3<G, V, HCons<E, L>, RR>() { | |
250 public RR f(final G f, final V v, final HCons<E, L> c) { | |
251 return p.apply(f, P.p(c.head(), h.foldRight(f, v, c.tail()))); | |
252 } | |
253 }); | |
254 } | |
255 | |
256 /** | |
257 * Folds a non-empty heterogeneous list. | |
258 * | |
259 * @param f A function with which to fold. | |
260 * @param v The value to substitute for the empty list. | |
261 * @param l The heterogeneous list to be folded. | |
262 * @return a value obtained by folding the given list with the given function. | |
263 */ | |
264 public R foldRight(final G f, final V v, final L l) { | |
265 return foldRight.f(f, v, l); | |
266 } | |
267 | |
268 } | |
269 | |
270 /** | |
271 * The nonempty list | |
272 */ | |
273 public static final class HCons<E, L extends HList<L>> extends HList<HCons<E, L>> { | |
274 private final E e; | |
275 private final L l; | |
276 | |
277 HCons(final E e, final L l) { | |
278 this.e = e; | |
279 this.l = l; | |
280 } | |
281 | |
282 public E head() { | |
283 return e; | |
284 } | |
285 | |
286 public L tail() { | |
287 return l; | |
288 } | |
289 | |
290 public <X> Apply<Unit, P2<X, HCons<E, L>>, HCons<X, HCons<E, L>>> extender() { | |
291 return Apply.cons(); | |
292 } | |
293 | |
294 public <X> HCons<X, HCons<E, L>> extend(final X e) { | |
295 return cons(e, this); | |
296 } | |
297 | |
298 } | |
299 | |
300 /** | |
301 * The empty list | |
302 */ | |
303 public static final class HNil extends HList<HNil> { | |
304 HNil() { | |
305 } | |
306 | |
307 public <E> HCons<E, HNil> extend(final E e) { | |
308 return cons(e, this); | |
309 } | |
310 | |
311 public <E> Apply<Unit, P2<E, HNil>, HCons<E, HNil>> extender() { | |
312 return Apply.cons(); | |
313 } | |
314 | |
315 } | |
316 } |