Mercurial > hg > Members > tatsuki > functionaljava-master > core
comparison src/main/java/fj/Equal.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; | |
2 | |
3 import static fj.Function.curry; | |
4 | |
5 import fj.data.*; | |
6 import fj.data.hlist.HList; | |
7 import fj.data.vector.V2; | |
8 import fj.data.vector.V3; | |
9 import fj.data.vector.V4; | |
10 import fj.data.vector.V5; | |
11 import fj.data.vector.V6; | |
12 import fj.data.vector.V7; | |
13 import fj.data.vector.V8; | |
14 | |
15 import java.math.BigInteger; | |
16 import java.math.BigDecimal; | |
17 | |
18 /** | |
19 * Tests for equality between two objects. | |
20 * | |
21 * @version %build.number% | |
22 */ | |
23 public final class Equal<A> { | |
24 private final F<A, F<A, Boolean>> f; | |
25 | |
26 private Equal(final F<A, F<A, Boolean>> f) { | |
27 this.f = f; | |
28 } | |
29 | |
30 /** | |
31 * Returns <code>true</code> if the two given arguments are equal, <code>false</code> otherwise. | |
32 * | |
33 * @param a1 An object to test for equality against another. | |
34 * @param a2 An object to test for equality against another. | |
35 * @return <code>true</code> if the two given arguments are equal, <code>false</code> otherwise. | |
36 */ | |
37 public boolean eq(final A a1, final A a2) { | |
38 return f.f(a1).f(a2); | |
39 } | |
40 | |
41 /** | |
42 * First-class equality check. | |
43 * | |
44 * @return A function that returns <code>true</code> if the two given arguments are equal. | |
45 */ | |
46 public F2<A, A, Boolean> eq() { | |
47 return new F2<A, A, Boolean>() { | |
48 public Boolean f(final A a, final A a1) { | |
49 return eq(a, a1); | |
50 } | |
51 }; | |
52 } | |
53 | |
54 /** | |
55 * Partially applied equality check. | |
56 * | |
57 * @param a An object to test for equality against another. | |
58 * @return A function that returns <code>true</code> if the given argument equals the argument to this method. | |
59 */ | |
60 public F<A, Boolean> eq(final A a) { | |
61 return new F<A, Boolean>() { | |
62 public Boolean f(final A a1) { | |
63 return eq(a, a1); | |
64 } | |
65 }; | |
66 } | |
67 | |
68 /** | |
69 * Maps the given function across this equal as a contra-variant functor. | |
70 * | |
71 * @param f The function to map. | |
72 * @return A new equal. | |
73 */ | |
74 public <B> Equal<B> comap(final F<B, A> f) { | |
75 return equal(F1Functions.o(F1Functions.o(F1Functions.<B, A, Boolean>andThen(f), this.f), f)); | |
76 } | |
77 | |
78 /** | |
79 * Constructs an equal instance from the given function. | |
80 * | |
81 * @param f The function to construct the equal with. | |
82 * @return An equal instance from the given function. | |
83 */ | |
84 public static <A> Equal<A> equal(final F<A, F<A, Boolean>> f) { | |
85 return new Equal<A>(f); | |
86 } | |
87 | |
88 /** | |
89 * Returns an equal instance that uses the {@link Object#equals(Object)} method to test for | |
90 * equality. | |
91 * | |
92 * @return An equal instance that uses the {@link Object#equals(Object)} method to test for | |
93 * equality. | |
94 */ | |
95 public static <A> Equal<A> anyEqual() { | |
96 return new Equal<A>(new F<A, F<A, Boolean>>() { | |
97 public F<A, Boolean> f(final A a1) { | |
98 return new F<A, Boolean>() { | |
99 public Boolean f(final A a2) { | |
100 return a1.equals(a2); | |
101 } | |
102 }; | |
103 } | |
104 }); | |
105 } | |
106 | |
107 /** | |
108 * An equal instance for the <code>boolean</code> type. | |
109 */ | |
110 public static final Equal<Boolean> booleanEqual = anyEqual(); | |
111 | |
112 /** | |
113 * An equal instance for the <code>byte</code> type. | |
114 */ | |
115 public static final Equal<Byte> byteEqual = anyEqual(); | |
116 | |
117 /** | |
118 * An equal instance for the <code>char</code> type. | |
119 */ | |
120 public static final Equal<Character> charEqual = anyEqual(); | |
121 | |
122 /** | |
123 * An equal instance for the <code>double</code> type. | |
124 */ | |
125 public static final Equal<Double> doubleEqual = anyEqual(); | |
126 | |
127 /** | |
128 * An equal instance for the <code>float</code> type. | |
129 */ | |
130 public static final Equal<Float> floatEqual = anyEqual(); | |
131 | |
132 /** | |
133 * An equal instance for the <code>int</code> type. | |
134 */ | |
135 public static final Equal<Integer> intEqual = anyEqual(); | |
136 | |
137 /** | |
138 * An equal instance for the <code>BigInteger</code> type. | |
139 */ | |
140 public static final Equal<BigInteger> bigintEqual = anyEqual(); | |
141 | |
142 /** | |
143 * An equal instance for the <code>BigDecimal</code> type. | |
144 */ | |
145 public static final Equal<BigDecimal> bigdecimalEqual = anyEqual(); | |
146 | |
147 /** | |
148 * An equal instance for the <code>long</code> type. | |
149 */ | |
150 public static final Equal<Long> longEqual = anyEqual(); | |
151 | |
152 /** | |
153 * An equal instance for the <code>short</code> type. | |
154 */ | |
155 public static final Equal<Short> shortEqual = anyEqual(); | |
156 | |
157 /** | |
158 * An equal instance for the {@link String} type. | |
159 */ | |
160 public static final Equal<String> stringEqual = anyEqual(); | |
161 | |
162 /** | |
163 * An equal instance for the {@link StringBuffer} type. | |
164 */ | |
165 public static final Equal<StringBuffer> stringBufferEqual = | |
166 new Equal<StringBuffer>(new F<StringBuffer, F<StringBuffer, Boolean>>() { | |
167 public F<StringBuffer, Boolean> f(final StringBuffer sb1) { | |
168 return new F<StringBuffer, Boolean>() { | |
169 public Boolean f(final StringBuffer sb2) { | |
170 if (sb1.length() == sb2.length()) { | |
171 for (int i = 0; i < sb1.length(); i++) | |
172 if (sb1.charAt(i) != sb2.charAt(i)) | |
173 return false; | |
174 return true; | |
175 } else | |
176 return false; | |
177 } | |
178 }; | |
179 } | |
180 }); | |
181 | |
182 /** | |
183 * An equal instance for the {@link StringBuilder} type. | |
184 */ | |
185 public static final Equal<StringBuilder> stringBuilderEqual = | |
186 new Equal<StringBuilder>(new F<StringBuilder, F<StringBuilder, Boolean>>() { | |
187 public F<StringBuilder, Boolean> f(final StringBuilder sb1) { | |
188 return new F<StringBuilder, Boolean>() { | |
189 public Boolean f(final StringBuilder sb2) { | |
190 if (sb1.length() == sb2.length()) { | |
191 for (int i = 0; i < sb1.length(); i++) | |
192 if (sb1.charAt(i) != sb2.charAt(i)) | |
193 return false; | |
194 return true; | |
195 } else | |
196 return false; | |
197 } | |
198 }; | |
199 } | |
200 }); | |
201 | |
202 /** | |
203 * An equal instance for the {@link Either} type. | |
204 * | |
205 * @param ea Equality across the left side of {@link Either}. | |
206 * @param eb Equality across the right side of {@link Either}. | |
207 * @return An equal instance for the {@link Either} type. | |
208 */ | |
209 public static <A, B> Equal<Either<A, B>> eitherEqual(final Equal<A> ea, final Equal<B> eb) { | |
210 return new Equal<Either<A, B>>(new F<Either<A, B>, F<Either<A, B>, Boolean>>() { | |
211 public F<Either<A, B>, Boolean> f(final Either<A, B> e1) { | |
212 return new F<Either<A, B>, Boolean>() { | |
213 public Boolean f(final Either<A, B> e2) { | |
214 return e1.isLeft() && e2.isLeft() && ea.f.f(e1.left().value()).f(e2.left().value()) || | |
215 e1.isRight() && e2.isRight() && eb.f.f(e1.right().value()).f(e2.right().value()); | |
216 } | |
217 }; | |
218 } | |
219 }); | |
220 } | |
221 | |
222 /** | |
223 * An equal instance for the {@link Validation} type. | |
224 * | |
225 * @param ea Equality across the failing side of {@link Validation}. | |
226 * @param eb Equality across the succeeding side of {@link Validation}. | |
227 * @return An equal instance for the {@link Validation} type. | |
228 */ | |
229 public static <A, B> Equal<Validation<A, B>> validationEqual(final Equal<A> ea, final Equal<B> eb) { | |
230 return eitherEqual(ea, eb).comap(Validation.<A, B>either()); | |
231 } | |
232 | |
233 /** | |
234 * An equal instance for the {@link List} type. | |
235 * | |
236 * @param ea Equality across the elements of the list. | |
237 * @return An equal instance for the {@link List} type. | |
238 */ | |
239 public static <A> Equal<List<A>> listEqual(final Equal<A> ea) { | |
240 return new Equal<List<A>>(new F<List<A>, F<List<A>, Boolean>>() { | |
241 public F<List<A>, Boolean> f(final List<A> a1) { | |
242 return new F<List<A>, Boolean>() { | |
243 public Boolean f(final List<A> a2) { | |
244 List<A> x1 = a1; | |
245 List<A> x2 = a2; | |
246 | |
247 while (x1.isNotEmpty() && x2.isNotEmpty()) { | |
248 if (!ea.eq(x1.head(), x2.head())) | |
249 return false; | |
250 | |
251 x1 = x1.tail(); | |
252 x2 = x2.tail(); | |
253 } | |
254 | |
255 return x1.isEmpty() && x2.isEmpty(); | |
256 } | |
257 }; | |
258 } | |
259 }); | |
260 } | |
261 | |
262 /** | |
263 * An equal instance for the {@link NonEmptyList} type. | |
264 * | |
265 * @param ea Equality across the elements of the non-empty list. | |
266 * @return An equal instance for the {@link NonEmptyList} type. | |
267 */ | |
268 public static <A> Equal<NonEmptyList<A>> nonEmptyListEqual(final Equal<A> ea) { | |
269 return listEqual(ea).comap(NonEmptyList.<A>toList_()); | |
270 } | |
271 | |
272 /** | |
273 * An equal instance for the {@link Option} type. | |
274 * | |
275 * @param ea Equality across the element of the option. | |
276 * @return An equal instance for the {@link Option} type. | |
277 */ | |
278 public static <A> Equal<Option<A>> optionEqual(final Equal<A> ea) { | |
279 return new Equal<Option<A>>(new F<Option<A>, F<Option<A>, Boolean>>() { | |
280 public F<Option<A>, Boolean> f(final Option<A> o1) { | |
281 return new F<Option<A>, Boolean>() { | |
282 public Boolean f(final Option<A> o2) { | |
283 return o1.isNone() && o2.isNone() || | |
284 o1.isSome() && o2.isSome() && ea.f.f(o1.some()).f(o2.some()); | |
285 } | |
286 }; | |
287 } | |
288 }); | |
289 } | |
290 | |
291 /** | |
292 * An equal instance for the {@link Stream} type. | |
293 * | |
294 * @param ea Equality across the elements of the stream. | |
295 * @return An equal instance for the {@link Stream} type. | |
296 */ | |
297 public static <A> Equal<Stream<A>> streamEqual(final Equal<A> ea) { | |
298 return new Equal<Stream<A>>(new F<Stream<A>, F<Stream<A>, Boolean>>() { | |
299 public F<Stream<A>, Boolean> f(final Stream<A> a1) { | |
300 return new F<Stream<A>, Boolean>() { | |
301 public Boolean f(final Stream<A> a2) { | |
302 Stream<A> x1 = a1; | |
303 Stream<A> x2 = a2; | |
304 | |
305 while (x1.isNotEmpty() && x2.isNotEmpty()) { | |
306 if (!ea.eq(x1.head(), x2.head())) | |
307 return false; | |
308 | |
309 x1 = x1.tail()._1(); | |
310 x2 = x2.tail()._1(); | |
311 } | |
312 | |
313 return x1.isEmpty() && x2.isEmpty(); | |
314 } | |
315 }; | |
316 } | |
317 }); | |
318 } | |
319 | |
320 /** | |
321 * An equal instance for the {@link Array} type. | |
322 * | |
323 * @param ea Equality across the elements of the array. | |
324 * @return An equal instance for the {@link Array} type. | |
325 */ | |
326 public static <A> Equal<Array<A>> arrayEqual(final Equal<A> ea) { | |
327 return new Equal<Array<A>>(new F<Array<A>, F<Array<A>, Boolean>>() { | |
328 public F<Array<A>, Boolean> f(final Array<A> a1) { | |
329 return new F<Array<A>, Boolean>() { | |
330 public Boolean f(final Array<A> a2) { | |
331 if (a1.length() == a2.length()) { | |
332 for (int i = 0; i < a1.length(); i++) { | |
333 if (!ea.eq(a1.get(i), a2.get(i))) | |
334 return false; | |
335 } | |
336 return true; | |
337 } else | |
338 return false; | |
339 } | |
340 }; | |
341 } | |
342 }); | |
343 } | |
344 | |
345 /** | |
346 * An equal instance for the {@link Tree} type. | |
347 * | |
348 * @param ea Equality across the elements of the tree. | |
349 * @return An equal instance for the {@link Tree} type. | |
350 */ | |
351 public static <A> Equal<Tree<A>> treeEqual(final Equal<A> ea) { | |
352 return new Equal<Tree<A>>(curry(new F2<Tree<A>, Tree<A>, Boolean>() { | |
353 public Boolean f(final Tree<A> t1, final Tree<A> t2) { | |
354 return ea.eq(t1.root(), t2.root()) && p1Equal(streamEqual(treeEqual(ea))).eq(t2.subForest(), t1.subForest()); | |
355 } | |
356 })); | |
357 } | |
358 | |
359 /** | |
360 * An equal instance for a product-1. | |
361 * | |
362 * @param ea Equality across the first element of the product. | |
363 * @return An equal instance for a product-1. | |
364 */ | |
365 public static <A> Equal<P1<A>> p1Equal(final Equal<A> ea) { | |
366 return new Equal<P1<A>>(new F<P1<A>, F<P1<A>, Boolean>>() { | |
367 public F<P1<A>, Boolean> f(final P1<A> p1) { | |
368 return new F<P1<A>, Boolean>() { | |
369 public Boolean f(final P1<A> p2) { | |
370 return ea.eq(p1._1(), p2._1()); | |
371 } | |
372 }; | |
373 } | |
374 }); | |
375 } | |
376 | |
377 /** | |
378 * An equal instance for a product-2. | |
379 * | |
380 * @param ea Equality across the first element of the product. | |
381 * @param eb Equality across the second element of the product. | |
382 * @return An equal instance for a product-2. | |
383 */ | |
384 public static <A, B> Equal<P2<A, B>> p2Equal(final Equal<A> ea, final Equal<B> eb) { | |
385 return new Equal<P2<A, B>>(new F<P2<A, B>, F<P2<A, B>, Boolean>>() { | |
386 public F<P2<A, B>, Boolean> f(final P2<A, B> p1) { | |
387 return new F<P2<A, B>, Boolean>() { | |
388 public Boolean f(final P2<A, B> p2) { | |
389 return ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()); | |
390 } | |
391 }; | |
392 } | |
393 }); | |
394 } | |
395 | |
396 /** | |
397 * An equal instance for a product-3. | |
398 * | |
399 * @param ea Equality across the first element of the product. | |
400 * @param eb Equality across the second element of the product. | |
401 * @param ec Equality across the third element of the product. | |
402 * @return An equal instance for a product-3. | |
403 */ | |
404 public static <A, B, C> Equal<P3<A, B, C>> p3Equal(final Equal<A> ea, final Equal<B> eb, final Equal<C> ec) { | |
405 return new Equal<P3<A, B, C>>(new F<P3<A, B, C>, F<P3<A, B, C>, Boolean>>() { | |
406 public F<P3<A, B, C>, Boolean> f(final P3<A, B, C> p1) { | |
407 return new F<P3<A, B, C>, Boolean>() { | |
408 public Boolean f(final P3<A, B, C> p2) { | |
409 return ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()); | |
410 } | |
411 }; | |
412 } | |
413 }); | |
414 } | |
415 | |
416 /** | |
417 * An equal instance for a product-4. | |
418 * | |
419 * @param ea Equality across the first element of the product. | |
420 * @param eb Equality across the second element of the product. | |
421 * @param ec Equality across the third element of the product. | |
422 * @param ed Equality across the fourth element of the product. | |
423 * @return An equal instance for a product-4. | |
424 */ | |
425 public static <A, B, C, D> Equal<P4<A, B, C, D>> p4Equal(final Equal<A> ea, final Equal<B> eb, final Equal<C> ec, | |
426 final Equal<D> ed) { | |
427 return new Equal<P4<A, B, C, D>>(new F<P4<A, B, C, D>, F<P4<A, B, C, D>, Boolean>>() { | |
428 public F<P4<A, B, C, D>, Boolean> f(final P4<A, B, C, D> p1) { | |
429 return new F<P4<A, B, C, D>, Boolean>() { | |
430 public Boolean f(final P4<A, B, C, D> p2) { | |
431 return ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && | |
432 ed.eq(p1._4(), p2._4()); | |
433 } | |
434 }; | |
435 } | |
436 }); | |
437 } | |
438 | |
439 /** | |
440 * An equal instance for a product-5. | |
441 * | |
442 * @param ea Equality across the first element of the product. | |
443 * @param eb Equality across the second element of the product. | |
444 * @param ec Equality across the third element of the product. | |
445 * @param ed Equality across the fourth element of the product. | |
446 * @param ee Equality across the fifth element of the product. | |
447 * @return An equal instance for a product-5. | |
448 */ | |
449 public static <A, B, C, D, E> Equal<P5<A, B, C, D, E>> p5Equal(final Equal<A> ea, final Equal<B> eb, | |
450 final Equal<C> ec, final Equal<D> ed, | |
451 final Equal<E> ee) { | |
452 return new Equal<P5<A, B, C, D, E>>(new F<P5<A, B, C, D, E>, F<P5<A, B, C, D, E>, Boolean>>() { | |
453 public F<P5<A, B, C, D, E>, Boolean> f(final P5<A, B, C, D, E> p1) { | |
454 return new F<P5<A, B, C, D, E>, Boolean>() { | |
455 public Boolean f(final P5<A, B, C, D, E> p2) { | |
456 return ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && | |
457 ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()); | |
458 } | |
459 }; | |
460 } | |
461 }); | |
462 } | |
463 | |
464 /** | |
465 * An equal instance for a product-6. | |
466 * | |
467 * @param ea Equality across the first element of the product. | |
468 * @param eb Equality across the second element of the product. | |
469 * @param ec Equality across the third element of the product. | |
470 * @param ed Equality across the fourth element of the product. | |
471 * @param ee Equality across the fifth element of the product. | |
472 * @param ef Equality across the sixth element of the product. | |
473 * @return An equal instance for a product-6. | |
474 */ | |
475 public static <A, B, C, D, E, F$> Equal<P6<A, B, C, D, E, F$>> p6Equal(final Equal<A> ea, final Equal<B> eb, | |
476 final Equal<C> ec, final Equal<D> ed, | |
477 final Equal<E> ee, final Equal<F$> ef) { | |
478 return new Equal<P6<A, B, C, D, E, F$>>(new F<P6<A, B, C, D, E, F$>, F<P6<A, B, C, D, E, F$>, Boolean>>() { | |
479 public F<P6<A, B, C, D, E, F$>, Boolean> f(final P6<A, B, C, D, E, F$> p1) { | |
480 return new F<P6<A, B, C, D, E, F$>, Boolean>() { | |
481 public Boolean f(final P6<A, B, C, D, E, F$> p2) { | |
482 return ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && | |
483 ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6()); | |
484 } | |
485 }; | |
486 } | |
487 }); | |
488 } | |
489 | |
490 /** | |
491 * An equal instance for a product-7. | |
492 * | |
493 * @param ea Equality across the first element of the product. | |
494 * @param eb Equality across the second element of the product. | |
495 * @param ec Equality across the third element of the product. | |
496 * @param ed Equality across the fourth element of the product. | |
497 * @param ee Equality across the fifth element of the product. | |
498 * @param ef Equality across the sixth element of the product. | |
499 * @param eg Equality across the seventh element of the product. | |
500 * @return An equal instance for a product-7. | |
501 */ | |
502 public static <A, B, C, D, E, F$, G> Equal<P7<A, B, C, D, E, F$, G>> p7Equal(final Equal<A> ea, final Equal<B> eb, | |
503 final Equal<C> ec, final Equal<D> ed, | |
504 final Equal<E> ee, final Equal<F$> ef, | |
505 final Equal<G> eg) { | |
506 return new Equal<P7<A, B, C, D, E, F$, G>>(new F<P7<A, B, C, D, E, F$, G>, F<P7<A, B, C, D, E, F$, G>, Boolean>>() { | |
507 public F<P7<A, B, C, D, E, F$, G>, Boolean> f(final P7<A, B, C, D, E, F$, G> p1) { | |
508 return new F<P7<A, B, C, D, E, F$, G>, Boolean>() { | |
509 public Boolean f(final P7<A, B, C, D, E, F$, G> p2) { | |
510 return ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && | |
511 ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6()) && | |
512 eg.eq(p1._7(), p2._7()); | |
513 } | |
514 }; | |
515 } | |
516 }); | |
517 } | |
518 | |
519 /** | |
520 * An equal instance for a product-8. | |
521 * | |
522 * @param ea Equality across the first element of the product. | |
523 * @param eb Equality across the second element of the product. | |
524 * @param ec Equality across the third element of the product. | |
525 * @param ed Equality across the fourth element of the product. | |
526 * @param ee Equality across the fifth element of the product. | |
527 * @param ef Equality across the sixth element of the product. | |
528 * @param eg Equality across the seventh element of the product. | |
529 * @param eh Equality across the eighth element of the product. | |
530 * @return An equal instance for a product-8. | |
531 */ | |
532 public static <A, B, C, D, E, F$, G, H> Equal<P8<A, B, C, D, E, F$, G, H>> p8Equal(final Equal<A> ea, | |
533 final Equal<B> eb, | |
534 final Equal<C> ec, | |
535 final Equal<D> ed, | |
536 final Equal<E> ee, | |
537 final Equal<F$> ef, | |
538 final Equal<G> eg, | |
539 final Equal<H> eh) { | |
540 return new Equal<P8<A, B, C, D, E, F$, G, H>>( | |
541 new F<P8<A, B, C, D, E, F$, G, H>, F<P8<A, B, C, D, E, F$, G, H>, Boolean>>() { | |
542 public F<P8<A, B, C, D, E, F$, G, H>, Boolean> f(final P8<A, B, C, D, E, F$, G, H> p1) { | |
543 return new F<P8<A, B, C, D, E, F$, G, H>, Boolean>() { | |
544 public Boolean f(final P8<A, B, C, D, E, F$, G, H> p2) { | |
545 return ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && | |
546 ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6()) && | |
547 eg.eq(p1._7(), p2._7()) && eh.eq(p1._8(), p2._8()); | |
548 } | |
549 }; | |
550 } | |
551 }); | |
552 } | |
553 | |
554 /** | |
555 * An equal instance for a vector-2. | |
556 * | |
557 * @param ea Equality across the elements of the vector. | |
558 * @return An equal instance for a vector-2. | |
559 */ | |
560 public static <A> Equal<V2<A>> v2Equal(final Equal<A> ea) { | |
561 return streamEqual(ea).comap(V2.<A>toStream_()); | |
562 } | |
563 | |
564 /** | |
565 * An equal instance for a vector-3. | |
566 * | |
567 * @param ea Equality across the elements of the vector. | |
568 * @return An equal instance for a vector-3. | |
569 */ | |
570 public static <A> Equal<V3<A>> v3Equal(final Equal<A> ea) { | |
571 return streamEqual(ea).comap(V3.<A>toStream_()); | |
572 } | |
573 | |
574 /** | |
575 * An equal instance for a vector-4. | |
576 * | |
577 * @param ea Equality across the elements of the vector. | |
578 * @return An equal instance for a vector-4. | |
579 */ | |
580 public static <A> Equal<V4<A>> v4Equal(final Equal<A> ea) { | |
581 return streamEqual(ea).comap(V4.<A>toStream_()); | |
582 } | |
583 | |
584 /** | |
585 * An equal instance for a vector-5. | |
586 * | |
587 * @param ea Equality across the elements of the vector. | |
588 * @return An equal instance for a vector-5. | |
589 */ | |
590 public static <A> Equal<V5<A>> v5Equal(final Equal<A> ea) { | |
591 return streamEqual(ea).comap(V5.<A>toStream_()); | |
592 } | |
593 | |
594 /** | |
595 * An equal instance for a vector-6. | |
596 * | |
597 * @param ea Equality across the elements of the vector. | |
598 * @return An equal instance for a vector-6. | |
599 */ | |
600 public static <A> Equal<V6<A>> v6Equal(final Equal<A> ea) { | |
601 return streamEqual(ea).comap(V6.<A>toStream_()); | |
602 } | |
603 | |
604 /** | |
605 * An equal instance for a vector-7. | |
606 * | |
607 * @param ea Equality across the elements of the vector. | |
608 * @return An equal instance for a vector-7. | |
609 */ | |
610 public static <A> Equal<V7<A>> v7Equal(final Equal<A> ea) { | |
611 return streamEqual(ea).comap(V7.<A>toStream_()); | |
612 } | |
613 | |
614 /** | |
615 * An equal instance for a vector-8. | |
616 * | |
617 * @param ea Equality across the elements of the vector. | |
618 * @return An equal instance for a vector-8. | |
619 */ | |
620 public static <A> Equal<V8<A>> v8Equal(final Equal<A> ea) { | |
621 return streamEqual(ea).comap(V8.<A>toStream_()); | |
622 } | |
623 | |
624 /** | |
625 * An equal instance for lazy strings. | |
626 */ | |
627 public static final Equal<LazyString> eq = streamEqual(charEqual).comap(LazyString.toStream); | |
628 | |
629 /** | |
630 * An equal instance for the empty heterogeneous list. | |
631 */ | |
632 public static final Equal<HList.HNil> hListEqual = anyEqual(); | |
633 | |
634 /** | |
635 * An equal instance for heterogeneous lists. | |
636 * | |
637 * @param e Equality for the first element of the list. | |
638 * @param l Equality for the rest of the list. | |
639 * @return an equal instance for a heterogeneous list. | |
640 */ | |
641 public static <E, L extends HList<L>> Equal<HList.HCons<E, L>> hListEqual(final Equal<E> e, final Equal<L> l) { | |
642 return equal(curry(new F2<HList.HCons<E, L>, HList.HCons<E, L>, Boolean>() { | |
643 public Boolean f(final HList.HCons<E, L> c1, final HList.HCons<E, L> c2) { | |
644 return e.eq(c1.head(), c2.head()) && l.eq(c1.tail(), c2.tail()); | |
645 } | |
646 })); | |
647 } | |
648 | |
649 /** | |
650 * Equal instance for sets. | |
651 * | |
652 * @param e Equality for the set elements. | |
653 * @return An equal instance for sets. | |
654 */ | |
655 public static <A> Equal<Set<A>> setEqual(final Equal<A> e) { | |
656 return equal(curry(new F2<Set<A>, Set<A>, Boolean>() { | |
657 public Boolean f(final Set<A> a, final Set<A> b) { | |
658 return streamEqual(e).eq(a.toStream(), b.toStream()); | |
659 } | |
660 })); | |
661 } | |
662 | |
663 public static <A, B> Equal<Writer<A, B>> writerEqual(Equal<A> eq1, Equal<B> eq2) { | |
664 return new Equal<Writer<A, B>>(w1 -> w2 -> Equal.p2Equal(eq1, eq2).eq(w1.run(), w2.run())); | |
665 } | |
666 | |
667 } |