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 }