001 package fj.pre; 002 003 import fj.F; 004 import fj.F2; 005 import fj.P1; 006 import fj.P2; 007 import fj.P3; 008 import fj.P4; 009 import fj.P5; 010 import fj.P6; 011 import fj.P7; 012 import fj.P8; 013 import static fj.FW.$; 014 import static fj.Function.curry; 015 import fj.data.hlist.HList; 016 import fj.data.Array; 017 import fj.data.Either; 018 import fj.data.LazyString; 019 import fj.data.List; 020 import fj.data.NonEmptyList; 021 import fj.data.Option; 022 import fj.data.Set; 023 import fj.data.Stream; 024 import fj.data.Tree; 025 import fj.data.Validation; 026 import fj.data.vector.V2; 027 import fj.data.vector.V3; 028 import fj.data.vector.V4; 029 import fj.data.vector.V5; 030 import fj.data.vector.V6; 031 import fj.data.vector.V7; 032 import fj.data.vector.V8; 033 034 import java.math.BigInteger; 035 import java.math.BigDecimal; 036 037 /** 038 * Tests for equality between two objects. 039 * 040 * @version %build.number%<br> 041 * <ul> 042 * <li>$LastChangedRevision: 144 $</li> 043 * <li>$LastChangedDate: 2009-05-27 01:24:17 +1000 (Wed, 27 May 2009) $</li> 044 * </ul> 045 */ 046 public final class Equal<A> { 047 private final F<A, F<A, Boolean>> f; 048 049 private Equal(final F<A, F<A, Boolean>> f) { 050 this.f = f; 051 } 052 053 /** 054 * Returns <code>true</code> if the two given arguments are equal, <code>false</code> otherwise. 055 * 056 * @param a1 An object to test for equality against another. 057 * @param a2 An object to test for equality against another. 058 * @return <code>true</code> if the two given arguments are equal, <code>false</code> otherwise. 059 */ 060 public boolean eq(final A a1, final A a2) { 061 return f.f(a1).f(a2); 062 } 063 064 /** 065 * First-class equality check. 066 * 067 * @return A function that returns <code>true</code> if the two given arguments are equal. 068 */ 069 public F2<A, A, Boolean> eq() { 070 return new F2<A, A, Boolean>() { 071 public Boolean f(final A a, final A a1) { 072 return eq(a, a1); 073 } 074 }; 075 } 076 077 /** 078 * Partially applied equality check. 079 * 080 * @param a An object to test for equality against another. 081 * @return A function that returns <code>true</code> if the given argument equals the argument to this method. 082 */ 083 public F<A, Boolean> eq(final A a) { 084 return new F<A, Boolean>() { 085 public Boolean f(final A a1) { 086 return eq(a, a1); 087 } 088 }; 089 } 090 091 /** 092 * Maps the given function across this equal as a contra-variant functor. 093 * 094 * @param f The function to map. 095 * @return A new equal. 096 */ 097 public <B> Equal<B> comap(final F<B, A> f) { 098 return equal($(f).<Boolean>andThen_().o(this.f).o(f)); 099 } 100 101 /** 102 * Constructs an equal instance from the given function. 103 * 104 * @param f The function to construct the equal with. 105 * @return An equal instance from the given function. 106 */ 107 public static <A> Equal<A> equal(final F<A, F<A, Boolean>> f) { 108 return new Equal<A>(f); 109 } 110 111 /** 112 * Returns an equal instance that uses the {@link Object#equals(Object)} method to test for 113 * equality. 114 * 115 * @return An equal instance that uses the {@link Object#equals(Object)} method to test for 116 * equality. 117 */ 118 public static <A> Equal<A> anyEqual() { 119 return new Equal<A>(new F<A, F<A, Boolean>>() { 120 public F<A, Boolean> f(final A a1) { 121 return new F<A, Boolean>() { 122 public Boolean f(final A a2) { 123 return a1.equals(a2); 124 } 125 }; 126 } 127 }); 128 } 129 130 /** 131 * An equal instance for the <code>boolean</code> type. 132 */ 133 public static final Equal<Boolean> booleanEqual = anyEqual(); 134 135 /** 136 * An equal instance for the <code>byte</code> type. 137 */ 138 public static final Equal<Byte> byteEqual = anyEqual(); 139 140 /** 141 * An equal instance for the <code>char</code> type. 142 */ 143 public static final Equal<Character> charEqual = anyEqual(); 144 145 /** 146 * An equal instance for the <code>double</code> type. 147 */ 148 public static final Equal<Double> doubleEqual = anyEqual(); 149 150 /** 151 * An equal instance for the <code>float</code> type. 152 */ 153 public static final Equal<Float> floatEqual = anyEqual(); 154 155 /** 156 * An equal instance for the <code>int</code> type. 157 */ 158 public static final Equal<Integer> intEqual = anyEqual(); 159 160 /** 161 * An equal instance for the <code>BigInteger</code> type. 162 */ 163 public static final Equal<BigInteger> bigintEqual = anyEqual(); 164 165 /** 166 * An equal instance for the <code>BigDecimal</code> type. 167 */ 168 public static final Equal<BigDecimal> bigdecimalEqual = anyEqual(); 169 170 /** 171 * An equal instance for the <code>long</code> type. 172 */ 173 public static final Equal<Long> longEqual = anyEqual(); 174 175 /** 176 * An equal instance for the <code>short</code> type. 177 */ 178 public static final Equal<Short> shortEqual = anyEqual(); 179 180 /** 181 * An equal instance for the {@link String} type. 182 */ 183 public static final Equal<String> stringEqual = anyEqual(); 184 185 /** 186 * An equal instance for the {@link StringBuffer} type. 187 */ 188 public static final Equal<StringBuffer> stringBufferEqual = 189 new Equal<StringBuffer>(new F<StringBuffer, F<StringBuffer, Boolean>>() { 190 public F<StringBuffer, Boolean> f(final StringBuffer sb1) { 191 return new F<StringBuffer, Boolean>() { 192 public Boolean f(final StringBuffer sb2) { 193 if (sb1.length() == sb2.length()) { 194 for (int i = 0; i < sb1.length(); i++) 195 if (sb1.charAt(i) != sb2.charAt(i)) 196 return false; 197 return true; 198 } else 199 return false; 200 } 201 }; 202 } 203 }); 204 205 /** 206 * An equal instance for the {@link StringBuilder} type. 207 */ 208 public static final Equal<StringBuilder> stringBuilderEqual = 209 new Equal<StringBuilder>(new F<StringBuilder, F<StringBuilder, Boolean>>() { 210 public F<StringBuilder, Boolean> f(final StringBuilder sb1) { 211 return new F<StringBuilder, Boolean>() { 212 public Boolean f(final StringBuilder sb2) { 213 if (sb1.length() == sb2.length()) { 214 for (int i = 0; i < sb1.length(); i++) 215 if (sb1.charAt(i) != sb2.charAt(i)) 216 return false; 217 return true; 218 } else 219 return false; 220 } 221 }; 222 } 223 }); 224 225 /** 226 * An equal instance for the {@link Either} type. 227 * 228 * @param ea Equality across the left side of {@link Either}. 229 * @param eb Equality across the right side of {@link Either}. 230 * @return An equal instance for the {@link Either} type. 231 */ 232 public static <A, B> Equal<Either<A, B>> eitherEqual(final Equal<A> ea, final Equal<B> eb) { 233 return new Equal<Either<A, B>>(new F<Either<A, B>, F<Either<A, B>, Boolean>>() { 234 public F<Either<A, B>, Boolean> f(final Either<A, B> e1) { 235 return new F<Either<A, B>, Boolean>() { 236 public Boolean f(final Either<A, B> e2) { 237 return e1.isLeft() && e2.isLeft() && ea.f.f(e1.left().value()).f(e2.left().value()) || 238 e1.isRight() && e2.isRight() && eb.f.f(e1.right().value()).f(e2.right().value()); 239 } 240 }; 241 } 242 }); 243 } 244 245 /** 246 * An equal instance for the {@link Validation} type. 247 * 248 * @param ea Equality across the failing side of {@link Validation}. 249 * @param eb Equality across the succeeding side of {@link Validation}. 250 * @return An equal instance for the {@link Validation} type. 251 */ 252 public static <A, B> Equal<Validation<A, B>> validationEqual(final Equal<A> ea, final Equal<B> eb) { 253 return eitherEqual(ea, eb).comap(Validation.<A, B>either()); 254 } 255 256 /** 257 * An equal instance for the {@link List} type. 258 * 259 * @param ea Equality across the elements of the list. 260 * @return An equal instance for the {@link List} type. 261 */ 262 public static <A> Equal<List<A>> listEqual(final Equal<A> ea) { 263 return new Equal<List<A>>(new F<List<A>, F<List<A>, Boolean>>() { 264 public F<List<A>, Boolean> f(final List<A> a1) { 265 return new F<List<A>, Boolean>() { 266 public Boolean f(final List<A> a2) { 267 List<A> x1 = a1; 268 List<A> x2 = a2; 269 270 while (x1.isNotEmpty() && x2.isNotEmpty()) { 271 if (!ea.eq(x1.head(), x2.head())) 272 return false; 273 274 x1 = x1.tail(); 275 x2 = x2.tail(); 276 } 277 278 return x1.isEmpty() && x2.isEmpty(); 279 } 280 }; 281 } 282 }); 283 } 284 285 /** 286 * An equal instance for the {@link NonEmptyList} type. 287 * 288 * @param ea Equality across the elements of the non-empty list. 289 * @return An equal instance for the {@link NonEmptyList} type. 290 */ 291 public static <A> Equal<NonEmptyList<A>> nonEmptyListEqual(final Equal<A> ea) { 292 return listEqual(ea).comap(NonEmptyList.<A>toList_()); 293 } 294 295 /** 296 * An equal instance for the {@link Option} type. 297 * 298 * @param ea Equality across the element of the option. 299 * @return An equal instance for the {@link Option} type. 300 */ 301 public static <A> Equal<Option<A>> optionEqual(final Equal<A> ea) { 302 return new Equal<Option<A>>(new F<Option<A>, F<Option<A>, Boolean>>() { 303 public F<Option<A>, Boolean> f(final Option<A> o1) { 304 return new F<Option<A>, Boolean>() { 305 public Boolean f(final Option<A> o2) { 306 return o1.isNone() && o2.isNone() || 307 o1.isSome() && o2.isSome() && ea.f.f(o1.some()).f(o2.some()); 308 } 309 }; 310 } 311 }); 312 } 313 314 /** 315 * An equal instance for the {@link Stream} type. 316 * 317 * @param ea Equality across the elements of the stream. 318 * @return An equal instance for the {@link Stream} type. 319 */ 320 public static <A> Equal<Stream<A>> streamEqual(final Equal<A> ea) { 321 return new Equal<Stream<A>>(new F<Stream<A>, F<Stream<A>, Boolean>>() { 322 public F<Stream<A>, Boolean> f(final Stream<A> a1) { 323 return new F<Stream<A>, Boolean>() { 324 public Boolean f(final Stream<A> a2) { 325 Stream<A> x1 = a1; 326 Stream<A> x2 = a2; 327 328 while (x1.isNotEmpty() && x2.isNotEmpty()) { 329 if (!ea.eq(x1.head(), x2.head())) 330 return false; 331 332 x1 = x1.tail()._1(); 333 x2 = x2.tail()._1(); 334 } 335 336 return x1.isEmpty() && x2.isEmpty(); 337 } 338 }; 339 } 340 }); 341 } 342 343 /** 344 * An equal instance for the {@link Array} type. 345 * 346 * @param ea Equality across the elements of the array. 347 * @return An equal instance for the {@link Array} type. 348 */ 349 public static <A> Equal<Array<A>> arrayEqual(final Equal<A> ea) { 350 return new Equal<Array<A>>(new F<Array<A>, F<Array<A>, Boolean>>() { 351 public F<Array<A>, Boolean> f(final Array<A> a1) { 352 return new F<Array<A>, Boolean>() { 353 public Boolean f(final Array<A> a2) { 354 if (a1.length() == a2.length()) { 355 for (int i = 0; i < a1.length(); i++) { 356 if (!ea.eq(a1.get(i), a2.get(i))) 357 return false; 358 } 359 return true; 360 } else 361 return false; 362 } 363 }; 364 } 365 }); 366 } 367 368 /** 369 * An equal instance for the {@link Tree} type. 370 * 371 * @param ea Equality across the elements of the tree. 372 * @return An equal instance for the {@link Tree} type. 373 */ 374 public static <A> Equal<Tree<A>> treeEqual(final Equal<A> ea) { 375 return new Equal<Tree<A>>(curry(new F2<Tree<A>, Tree<A>, Boolean>() { 376 public Boolean f(final Tree<A> t1, final Tree<A> t2) { 377 return ea.eq(t1.root(), t2.root()) && p1Equal(streamEqual(treeEqual(ea))).eq(t2.subForest(), t1.subForest()); 378 } 379 })); 380 } 381 382 /** 383 * An equal instance for a product-1. 384 * 385 * @param ea Equality across the first element of the product. 386 * @return An equal instance for a product-1. 387 */ 388 public static <A> Equal<P1<A>> p1Equal(final Equal<A> ea) { 389 return new Equal<P1<A>>(new F<P1<A>, F<P1<A>, Boolean>>() { 390 public F<P1<A>, Boolean> f(final P1<A> p1) { 391 return new F<P1<A>, Boolean>() { 392 public Boolean f(final P1<A> p2) { 393 return ea.eq(p1._1(), p2._1()); 394 } 395 }; 396 } 397 }); 398 } 399 400 /** 401 * An equal instance for a product-2. 402 * 403 * @param ea Equality across the first element of the product. 404 * @param eb Equality across the second element of the product. 405 * @return An equal instance for a product-2. 406 */ 407 public static <A, B> Equal<P2<A, B>> p2Equal(final Equal<A> ea, final Equal<B> eb) { 408 return new Equal<P2<A, B>>(new F<P2<A, B>, F<P2<A, B>, Boolean>>() { 409 public F<P2<A, B>, Boolean> f(final P2<A, B> p1) { 410 return new F<P2<A, B>, Boolean>() { 411 public Boolean f(final P2<A, B> p2) { 412 return ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()); 413 } 414 }; 415 } 416 }); 417 } 418 419 /** 420 * An equal instance for a product-3. 421 * 422 * @param ea Equality across the first element of the product. 423 * @param eb Equality across the second element of the product. 424 * @param ec Equality across the third element of the product. 425 * @return An equal instance for a product-3. 426 */ 427 public static <A, B, C> Equal<P3<A, B, C>> p3Equal(final Equal<A> ea, final Equal<B> eb, final Equal<C> ec) { 428 return new Equal<P3<A, B, C>>(new F<P3<A, B, C>, F<P3<A, B, C>, Boolean>>() { 429 public F<P3<A, B, C>, Boolean> f(final P3<A, B, C> p1) { 430 return new F<P3<A, B, C>, Boolean>() { 431 public Boolean f(final P3<A, B, C> p2) { 432 return ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()); 433 } 434 }; 435 } 436 }); 437 } 438 439 /** 440 * An equal instance for a product-4. 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 * @return An equal instance for a product-4. 447 */ 448 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, 449 final Equal<D> ed) { 450 return new Equal<P4<A, B, C, D>>(new F<P4<A, B, C, D>, F<P4<A, B, C, D>, Boolean>>() { 451 public F<P4<A, B, C, D>, Boolean> f(final P4<A, B, C, D> p1) { 452 return new F<P4<A, B, C, D>, Boolean>() { 453 public Boolean f(final P4<A, B, C, D> p2) { 454 return ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && 455 ed.eq(p1._4(), p2._4()); 456 } 457 }; 458 } 459 }); 460 } 461 462 /** 463 * An equal instance for a product-5. 464 * 465 * @param ea Equality across the first element of the product. 466 * @param eb Equality across the second element of the product. 467 * @param ec Equality across the third element of the product. 468 * @param ed Equality across the fourth element of the product. 469 * @param ee Equality across the fifth element of the product. 470 * @return An equal instance for a product-5. 471 */ 472 public static <A, B, C, D, E> Equal<P5<A, B, C, D, E>> p5Equal(final Equal<A> ea, final Equal<B> eb, 473 final Equal<C> ec, final Equal<D> ed, 474 final Equal<E> ee) { 475 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>>() { 476 public F<P5<A, B, C, D, E>, Boolean> f(final P5<A, B, C, D, E> p1) { 477 return new F<P5<A, B, C, D, E>, Boolean>() { 478 public Boolean f(final P5<A, B, C, D, E> p2) { 479 return ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && 480 ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()); 481 } 482 }; 483 } 484 }); 485 } 486 487 /** 488 * An equal instance for a product-6. 489 * 490 * @param ea Equality across the first element of the product. 491 * @param eb Equality across the second element of the product. 492 * @param ec Equality across the third element of the product. 493 * @param ed Equality across the fourth element of the product. 494 * @param ee Equality across the fifth element of the product. 495 * @param ef Equality across the sixth element of the product. 496 * @return An equal instance for a product-6. 497 */ 498 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, 499 final Equal<C> ec, final Equal<D> ed, 500 final Equal<E> ee, final Equal<F$> ef) { 501 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>>() { 502 public F<P6<A, B, C, D, E, F$>, Boolean> f(final P6<A, B, C, D, E, F$> p1) { 503 return new F<P6<A, B, C, D, E, F$>, Boolean>() { 504 public Boolean f(final P6<A, B, C, D, E, F$> p2) { 505 return ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && 506 ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6()); 507 } 508 }; 509 } 510 }); 511 } 512 513 /** 514 * An equal instance for a product-7. 515 * 516 * @param ea Equality across the first element of the product. 517 * @param eb Equality across the second element of the product. 518 * @param ec Equality across the third element of the product. 519 * @param ed Equality across the fourth element of the product. 520 * @param ee Equality across the fifth element of the product. 521 * @param ef Equality across the sixth element of the product. 522 * @param eg Equality across the seventh element of the product. 523 * @return An equal instance for a product-7. 524 */ 525 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, 526 final Equal<C> ec, final Equal<D> ed, 527 final Equal<E> ee, final Equal<F$> ef, 528 final Equal<G> eg) { 529 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>>() { 530 public F<P7<A, B, C, D, E, F$, G>, Boolean> f(final P7<A, B, C, D, E, F$, G> p1) { 531 return new F<P7<A, B, C, D, E, F$, G>, Boolean>() { 532 public Boolean f(final P7<A, B, C, D, E, F$, G> p2) { 533 return ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && 534 ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6()) && 535 eg.eq(p1._7(), p2._7()); 536 } 537 }; 538 } 539 }); 540 } 541 542 /** 543 * An equal instance for a product-8. 544 * 545 * @param ea Equality across the first element of the product. 546 * @param eb Equality across the second element of the product. 547 * @param ec Equality across the third element of the product. 548 * @param ed Equality across the fourth element of the product. 549 * @param ee Equality across the fifth element of the product. 550 * @param ef Equality across the sixth element of the product. 551 * @param eg Equality across the seventh element of the product. 552 * @param eh Equality across the eighth element of the product. 553 * @return An equal instance for a product-8. 554 */ 555 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, 556 final Equal<B> eb, 557 final Equal<C> ec, 558 final Equal<D> ed, 559 final Equal<E> ee, 560 final Equal<F$> ef, 561 final Equal<G> eg, 562 final Equal<H> eh) { 563 return new Equal<P8<A, B, C, D, E, F$, G, H>>( 564 new F<P8<A, B, C, D, E, F$, G, H>, F<P8<A, B, C, D, E, F$, G, H>, Boolean>>() { 565 public F<P8<A, B, C, D, E, F$, G, H>, Boolean> f(final P8<A, B, C, D, E, F$, G, H> p1) { 566 return new F<P8<A, B, C, D, E, F$, G, H>, Boolean>() { 567 public Boolean f(final P8<A, B, C, D, E, F$, G, H> p2) { 568 return ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && 569 ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6()) && 570 eg.eq(p1._7(), p2._7()) && eh.eq(p1._8(), p2._8()); 571 } 572 }; 573 } 574 }); 575 } 576 577 /** 578 * An equal instance for a vector-2. 579 * 580 * @param ea Equality across the elements of the vector. 581 * @return An equal instance for a vector-2. 582 */ 583 public static <A> Equal<V2<A>> v2Equal(final Equal<A> ea) { 584 return streamEqual(ea).comap(V2.<A>toStream_()); 585 } 586 587 /** 588 * An equal instance for a vector-3. 589 * 590 * @param ea Equality across the elements of the vector. 591 * @return An equal instance for a vector-3. 592 */ 593 public static <A> Equal<V3<A>> v3Equal(final Equal<A> ea) { 594 return streamEqual(ea).comap(V3.<A>toStream_()); 595 } 596 597 /** 598 * An equal instance for a vector-4. 599 * 600 * @param ea Equality across the elements of the vector. 601 * @return An equal instance for a vector-4. 602 */ 603 public static <A> Equal<V4<A>> v4Equal(final Equal<A> ea) { 604 return streamEqual(ea).comap(V4.<A>toStream_()); 605 } 606 607 /** 608 * An equal instance for a vector-5. 609 * 610 * @param ea Equality across the elements of the vector. 611 * @return An equal instance for a vector-5. 612 */ 613 public static <A> Equal<V5<A>> v5Equal(final Equal<A> ea) { 614 return streamEqual(ea).comap(V5.<A>toStream_()); 615 } 616 617 /** 618 * An equal instance for a vector-6. 619 * 620 * @param ea Equality across the elements of the vector. 621 * @return An equal instance for a vector-6. 622 */ 623 public static <A> Equal<V6<A>> v6Equal(final Equal<A> ea) { 624 return streamEqual(ea).comap(V6.<A>toStream_()); 625 } 626 627 /** 628 * An equal instance for a vector-7. 629 * 630 * @param ea Equality across the elements of the vector. 631 * @return An equal instance for a vector-7. 632 */ 633 public static <A> Equal<V7<A>> v7Equal(final Equal<A> ea) { 634 return streamEqual(ea).comap(V7.<A>toStream_()); 635 } 636 637 /** 638 * An equal instance for a vector-8. 639 * 640 * @param ea Equality across the elements of the vector. 641 * @return An equal instance for a vector-8. 642 */ 643 public static <A> Equal<V8<A>> v8Equal(final Equal<A> ea) { 644 return streamEqual(ea).comap(V8.<A>toStream_()); 645 } 646 647 /** 648 * An equal instance for lazy strings. 649 */ 650 public static final Equal<LazyString> eq = streamEqual(charEqual).comap(LazyString.toStream); 651 652 /** 653 * An equal instance for the empty heterogeneous list. 654 */ 655 public static final Equal<HList.HNil> hListEqual = anyEqual(); 656 657 /** 658 * An equal instance for heterogeneous lists. 659 * 660 * @param e Equality for the first element of the list. 661 * @param l Equality for the rest of the list. 662 * @return an equal instance for a heterogeneous list. 663 */ 664 public static <E, L extends HList<L>> Equal<HList.HCons<E, L>> hListEqual(final Equal<E> e, final Equal<L> l) { 665 return equal(curry(new F2<HList.HCons<E, L>, HList.HCons<E, L>, Boolean>() { 666 public Boolean f(final HList.HCons<E, L> c1, final HList.HCons<E, L> c2) { 667 return e.eq(c1.head(), c2.head()) && l.eq(c1.tail(), c2.tail()); 668 } 669 })); 670 } 671 672 /** 673 * Equal instance for sets. 674 * 675 * @param e Equality for the set elements. 676 * @return An equal instance for sets. 677 */ 678 public static <A> Equal<Set<A>> setEqual(final Equal<A> e) { 679 return equal(curry(new F2<Set<A>, Set<A>, Boolean>() { 680 public Boolean f(final Set<A> a, final Set<A> b) { 681 return streamEqual(e).eq(a.toStream(), b.toStream()); 682 } 683 })); 684 } 685 }