Skip to content

Commit 6945c78

Browse files
committed
Finish migrating Equal to use optimizable definition
1 parent 25d10ea commit 6945c78

1 file changed

Lines changed: 81 additions & 33 deletions

File tree

core/src/main/java/fj/Equal.java

Lines changed: 81 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,13 @@ default boolean equal(A a1, A a2) {
5454
*/
5555
interface AlternateDefinition<A> extends Definition<A> {
5656

57+
@Override
58+
boolean equal(A a1, A a2);
59+
5760
@Override
5861
default F<A, Boolean> equal(A a) {
5962
return a2 -> equal(a, a2);
6063
}
61-
62-
@Override
63-
boolean equal(A a1, A a2);
6464
}
6565

6666
private final Definition<A> def;
@@ -144,20 +144,20 @@ public static <A> Equal<A> equal(final F<A, F<A, Boolean>> f) {
144144
/**
145145
* Constructs an equal instance from the given definition.
146146
*
147-
* @param definition The minimal definition of the equal instance.
147+
* @param definition a definition of the equal instance.
148148
* @return An equal instance from the given function.
149149
*/
150150
public static <A> Equal<A> equalDef(final Definition<A> definition) {
151151
return new Equal<>(definition);
152152
}
153153

154154
/**
155-
* Constructs an equal instance from the given definition.
155+
* Constructs an equal instance from the given (alternative) definition.
156156
*
157-
* @param definition The minimal definition of the equal instance.
157+
* @param definition a definition of the equal instance.
158158
* @return An equal instance from the given function.
159159
*/
160-
public static <A> Equal<A> equalAltDef(final AlternateDefinition<A> definition) {
160+
public static <A> Equal<A> equalDef(final AlternateDefinition<A> definition) {
161161
return new Equal<>(definition);
162162
}
163163

@@ -246,7 +246,7 @@ public boolean equal(A a1, A a2) {
246246
* An equal instance for the {@link StringBuffer} type.
247247
*/
248248
public static final Equal<StringBuffer> stringBufferEqual =
249-
equalAltDef((sb1, sb2) -> {
249+
equalDef((sb1, sb2) -> {
250250
if (sb1.length() == sb2.length()) {
251251
for (int i = 0; i < sb1.length(); i++)
252252
if (sb1.charAt(i) != sb2.charAt(i))
@@ -260,7 +260,7 @@ public boolean equal(A a1, A a2) {
260260
* An equal instance for the {@link StringBuilder} type.
261261
*/
262262
public static final Equal<StringBuilder> stringBuilderEqual =
263-
equalAltDef((sb1, sb2) -> {
263+
equalDef((sb1, sb2) -> {
264264
if (sb1.length() == sb2.length()) {
265265
for (int i = 0; i < sb1.length(); i++)
266266
if (sb1.charAt(i) != sb2.charAt(i))
@@ -305,7 +305,7 @@ public static <A, B> Equal<Validation<A, B>> validationEqual(final Equal<A> ea,
305305
*/
306306
public static <A> Equal<List<A>> listEqual(final Equal<A> ea) {
307307
Definition<A> eaDef = ea.def;
308-
return equalAltDef((a1, a2) -> {
308+
return equalDef((a1, a2) -> {
309309
List<A> x1 = a1;
310310
List<A> x2 = a2;
311311

@@ -357,7 +357,7 @@ public static <A> Equal<Seq<A>> seqEqual(final Equal<A> e) {
357357
*/
358358
public static <A> Equal<Stream<A>> streamEqual(final Equal<A> ea) {
359359
Definition<A> eaDef = ea.def;
360-
return equalAltDef((a1, a2) -> {
360+
return equalDef((a1, a2) -> {
361361
Stream<A> x1 = a1;
362362
Stream<A> x2 = a2;
363363

@@ -381,7 +381,7 @@ public static <A> Equal<Stream<A>> streamEqual(final Equal<A> ea) {
381381
*/
382382
public static <A> Equal<Array<A>> arrayEqual(final Equal<A> ea) {
383383
Definition<A> eaDef = ea.def;
384-
return equalAltDef((a1, a2) -> {
384+
return equalDef((a1, a2) -> {
385385
if (a1.length() == a2.length()) {
386386
for (int i = 0; i < a1.length(); i++) {
387387
if (!eaDef.equal(a1.get(i), a2.get(i)))
@@ -400,7 +400,18 @@ public static <A> Equal<Array<A>> arrayEqual(final Equal<A> ea) {
400400
* @return An equal instance for the {@link Tree} type.
401401
*/
402402
public static <A> Equal<Tree<A>> treeEqual(final Equal<A> ea) {
403-
return equalAltDef((t1, t2) -> ea.eq(t1.root(), t2.root()) && p1Equal(streamEqual(treeEqual(ea))).eq(t2.subForest(), t1.subForest()));
403+
Definition<A> eaDef = ea.def;
404+
return equalDef(new AlternateDefinition<Tree<A>>() {
405+
406+
final Definition<P1<Stream<Tree<A>>>> subForestEqDef = p1Equal(streamEqual(equalDef(this))).def;
407+
408+
@Override
409+
public boolean equal(Tree<A> t1, Tree<A> t2) {
410+
return eaDef.equal(t1.root(), t2.root())
411+
&& subForestEqDef.equal(t1.subForest(), t2.subForest());
412+
413+
}
414+
});
404415
}
405416

406417
/**
@@ -410,7 +421,7 @@ public static <A> Equal<Tree<A>> treeEqual(final Equal<A> ea) {
410421
* @return An equal instance for a product-1.
411422
*/
412423
public static <A> Equal<P1<A>> p1Equal(final Equal<A> ea) {
413-
return equalAltDef((p1, p2) -> ea.eq(p1._1(), p2._1()));
424+
return ea.contramap(P1.__1());
414425
}
415426

416427
/**
@@ -421,7 +432,9 @@ public static <A> Equal<P1<A>> p1Equal(final Equal<A> ea) {
421432
* @return An equal instance for a product-2.
422433
*/
423434
public static <A, B> Equal<P2<A, B>> p2Equal(final Equal<A> ea, final Equal<B> eb) {
424-
return equalAltDef((p1, p2)-> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()));
435+
Definition<A> eaDef = ea.def;
436+
Definition<B> ebDef = eb.def;
437+
return equalDef((p1, p2)-> eaDef.equal(p1._1(), p2._1()) && ebDef.equal(p1._2(), p2._2()));
425438
}
426439

427440
/**
@@ -433,7 +446,10 @@ public static <A, B> Equal<P2<A, B>> p2Equal(final Equal<A> ea, final Equal<B> e
433446
* @return An equal instance for a product-3.
434447
*/
435448
public static <A, B, C> Equal<P3<A, B, C>> p3Equal(final Equal<A> ea, final Equal<B> eb, final Equal<C> ec) {
436-
return equalAltDef((p1, p2) -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()));
449+
Definition<A> eaDef = ea.def;
450+
Definition<B> ebDef = eb.def;
451+
Definition<C> ecDef = ec.def;
452+
return equalDef((p1, p2) -> eaDef.equal(p1._1(), p2._1()) && ebDef.equal(p1._2(), p2._2()) && ecDef.equal(p1._3(), p2._3()));
437453
}
438454

439455
/**
@@ -447,8 +463,12 @@ public static <A, B, C> Equal<P3<A, B, C>> p3Equal(final Equal<A> ea, final Equa
447463
*/
448464
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,
449465
final Equal<D> ed) {
450-
return equalAltDef((p1, p2) -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) &&
451-
ed.eq(p1._4(), p2._4()));
466+
Definition<A> eaDef = ea.def;
467+
Definition<B> ebDef = eb.def;
468+
Definition<C> ecDef = ec.def;
469+
Definition<D> edDef = ed.def;
470+
return equalDef((p1, p2) -> eaDef.equal(p1._1(), p2._1()) && ebDef.equal(p1._2(), p2._2()) && ecDef.equal(p1._3(), p2._3()) &&
471+
edDef.equal(p1._4(), p2._4()));
452472
}
453473

454474
/**
@@ -464,8 +484,13 @@ public static <A, B, C, D> Equal<P4<A, B, C, D>> p4Equal(final Equal<A> ea, fina
464484
public static <A, B, C, D, E> Equal<P5<A, B, C, D, E>> p5Equal(final Equal<A> ea, final Equal<B> eb,
465485
final Equal<C> ec, final Equal<D> ed,
466486
final Equal<E> ee) {
467-
return equalAltDef((p1, p2) -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) &&
468-
ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()));
487+
Definition<A> eaDef = ea.def;
488+
Definition<B> ebDef = eb.def;
489+
Definition<C> ecDef = ec.def;
490+
Definition<D> edDef = ed.def;
491+
Definition<E> eeDef = ee.def;
492+
return equalDef((p1, p2) -> eaDef.equal(p1._1(), p2._1()) && ebDef.equal(p1._2(), p2._2()) && ecDef.equal(p1._3(), p2._3()) &&
493+
edDef.equal(p1._4(), p2._4()) && eeDef.equal(p1._5(), p2._5()));
469494
}
470495

471496
/**
@@ -482,8 +507,14 @@ public static <A, B, C, D, E> Equal<P5<A, B, C, D, E>> p5Equal(final Equal<A> ea
482507
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,
483508
final Equal<C> ec, final Equal<D> ed,
484509
final Equal<E> ee, final Equal<F$> ef) {
485-
return equalAltDef((p1, p2) -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) &&
486-
ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6()));
510+
Definition<A> eaDef = ea.def;
511+
Definition<B> ebDef = eb.def;
512+
Definition<C> ecDef = ec.def;
513+
Definition<D> edDef = ed.def;
514+
Definition<E> eeDef = ee.def;
515+
Definition<F$> efDef = ef.def;
516+
return equalDef((p1, p2) -> eaDef.equal(p1._1(), p2._1()) && ebDef.equal(p1._2(), p2._2()) && ecDef.equal(p1._3(), p2._3()) &&
517+
edDef.equal(p1._4(), p2._4()) && eeDef.equal(p1._5(), p2._5()) && efDef.equal(p1._6(), p2._6()));
487518
}
488519

489520
/**
@@ -502,9 +533,16 @@ public static <A, B, C, D, E> Equal<P5<A, B, C, D, E>> p5Equal(final Equal<A> ea
502533
final Equal<C> ec, final Equal<D> ed,
503534
final Equal<E> ee, final Equal<F$> ef,
504535
final Equal<G> eg) {
505-
return equalAltDef((p1, p2) -> 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-
eg.eq(p1._7(), p2._7()));
536+
Definition<A> eaDef = ea.def;
537+
Definition<B> ebDef = eb.def;
538+
Definition<C> ecDef = ec.def;
539+
Definition<D> edDef = ed.def;
540+
Definition<E> eeDef = ee.def;
541+
Definition<F$> efDef = ef.def;
542+
Definition<G> egDef = eg.def;
543+
return equalDef((p1, p2) -> eaDef.equal(p1._1(), p2._1()) && ebDef.equal(p1._2(), p2._2()) && ecDef.equal(p1._3(), p2._3()) &&
544+
edDef.equal(p1._4(), p2._4()) && eeDef.equal(p1._5(), p2._5()) && efDef.equal(p1._6(), p2._6()) &&
545+
egDef.equal(p1._7(), p2._7()));
508546
}
509547

510548
/**
@@ -528,10 +566,18 @@ public static <A, B, C, D, E> Equal<P5<A, B, C, D, E>> p5Equal(final Equal<A> ea
528566
final Equal<F$> ef,
529567
final Equal<G> eg,
530568
final Equal<H> eh) {
531-
return equalAltDef(
532-
(p1, p2) -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) &&
533-
ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6()) &&
534-
eg.eq(p1._7(), p2._7()) && eh.eq(p1._8(), p2._8()));
569+
Definition<A> eaDef = ea.def;
570+
Definition<B> ebDef = eb.def;
571+
Definition<C> ecDef = ec.def;
572+
Definition<D> edDef = ed.def;
573+
Definition<E> eeDef = ee.def;
574+
Definition<F$> efDef = ef.def;
575+
Definition<G> egDef = eg.def;
576+
Definition<H> ehDef = eh.def;
577+
return equalDef(
578+
(p1, p2) -> eaDef.equal(p1._1(), p2._1()) && ebDef.equal(p1._2(), p2._2()) && ecDef.equal(p1._3(), p2._3()) &&
579+
edDef.equal(p1._4(), p2._4()) && eeDef.equal(p1._5(), p2._5()) && efDef.equal(p1._6(), p2._6()) &&
580+
egDef.equal(p1._7(), p2._7()) && ehDef.equal(p1._8(), p2._8()));
535581
}
536582

537583
/**
@@ -622,7 +668,9 @@ public static <A> Equal<V8<A>> v8Equal(final Equal<A> ea) {
622668
* @return an equal instance for a heterogeneous list.
623669
*/
624670
public static <E, L extends HList<L>> Equal<HList.HCons<E, L>> hListEqual(final Equal<E> e, final Equal<L> l) {
625-
return equal(curry((HList.HCons<E, L> c1, HList.HCons<E, L> c2) -> e.eq(c1.head(), c2.head()) && l.eq(c1.tail(), c2.tail())));
671+
Definition<E> eDef = e.def;
672+
Definition<L> lDef = l.def;
673+
return equalDef((c1, c2) -> eDef.equal(c1.head(), c2.head()) && lDef.equal(c1.tail(), c2.tail()));
626674
}
627675

628676
/**
@@ -632,15 +680,15 @@ public static <E, L extends HList<L>> Equal<HList.HCons<E, L>> hListEqual(final
632680
* @return An equal instance for sets.
633681
*/
634682
public static <A> Equal<Set<A>> setEqual(final Equal<A> e) {
635-
return equal(curry((Set<A> a, Set<A> b) -> streamEqual(e).eq(a.toStream(), b.toStream())));
683+
return streamEqual(e).contramap(Set::toStream);
636684
}
637685

638686
public static <K, V> Equal<TreeMap<K, V>> treeMapEqual(Equal<K> k, Equal<V> v) {
639-
return equal(t1 -> t2 -> streamEqual(p2Equal(k, v)).eq(t1.toStream(), t2.toStream()));
687+
return streamEqual(p2Equal(k, v)).contramap(TreeMap::toStream);
640688
}
641689

642690
public static <A, B> Equal<Writer<A, B>> writerEqual(Equal<A> eq1, Equal<B> eq2) {
643-
return equal(w1 -> w2 -> p2Equal(eq1, eq2).eq(w1.run(), w2.run()));
691+
return p2Equal(eq1, eq2).contramap(Writer::run);
644692
}
645693

646694
/**

0 commit comments

Comments
 (0)