11package fj ;
22
3- import static fj .Function .curry ;
4-
5- import fj .data .*;
3+ import fj .data .Array ;
4+ import fj .data .Either ;
5+ import fj .data .LazyString ;
6+ import fj .data .List ;
7+ import fj .data .Natural ;
8+ import fj .data .NonEmptyList ;
9+ import fj .data .Option ;
10+ import fj .data .Seq ;
11+ import fj .data .Set ;
12+ import fj .data .Stream ;
13+ import fj .data .Tree ;
14+ import fj .data .TreeMap ;
15+ import fj .data .Validation ;
16+ import fj .data .Writer ;
617import fj .data .hlist .HList ;
718import fj .data .vector .V2 ;
819import fj .data .vector .V3 ;
1223import fj .data .vector .V7 ;
1324import fj .data .vector .V8 ;
1425
15- import java .math .BigInteger ;
1626import java .math .BigDecimal ;
27+ import java .math .BigInteger ;
28+
29+ import static fj .Function .compose ;
30+ import static fj .Function .constant ;
31+ import static fj .Function .curry ;
1732
1833/**
1934 * Tests for equality between two objects.
2035 *
2136 * @version %build.number%
2237 */
2338public final class Equal <A > {
24- private final F <A , F <A , Boolean >> f ;
2539
26- private Equal (final F <A , F <A , Boolean >> f ) {
27- this .f = f ;
40+ /**
41+ * Primitives functions of Equal: minimal definition and overridable methods.
42+ */
43+ interface Definition <A > {
44+
45+ F <A , Boolean > equal (A a );
46+
47+ default boolean equal (A a1 , A a2 ) {
48+ return equal (a1 ).f (a2 );
49+ }
50+ }
51+
52+ /**
53+ * Primitives functions of Equal: alternative minimal definition and overridable methods.
54+ */
55+ interface AlternateDefinition <A > extends Definition <A > {
56+
57+ @ Override
58+ default F <A , Boolean > equal (A a ) {
59+ return a2 -> equal (a , a2 );
60+ }
61+
62+ @ Override
63+ boolean equal (A a1 , A a2 );
64+ }
65+
66+ private final Definition <A > def ;
67+
68+ private Equal (final Definition <A > def ) {
69+ this .def = def ;
2870 }
2971
3072 /**
@@ -35,7 +77,7 @@ private Equal(final F<A, F<A, Boolean>> f) {
3577 * @return <code>true</code> if the two given arguments are equal, <code>false</code> otherwise.
3678 */
3779 public boolean eq (final A a1 , final A a2 ) {
38- return f . f (a1 ). f ( a2 );
80+ return def . equal (a1 , a2 );
3981 }
4082
4183 /**
@@ -46,7 +88,7 @@ public boolean eq(final A a1, final A a2) {
4688 * @return <code>true</code> if the two given arguments are not equal, <code>false</code> otherwise.
4789 */
4890 public boolean notEq (final A a1 , final A a2 ) {
49- return !eq (a1 , a2 );
91+ return !def . equal (a1 , a2 );
5092 }
5193
5294 /**
@@ -55,7 +97,7 @@ public boolean notEq(final A a1, final A a2) {
5597 * @return A function that returns <code>true</code> if the two given arguments are equal.
5698 */
5799 public F2 <A , A , Boolean > eq () {
58- return this :: eq ;
100+ return def :: equal ;
59101 }
60102
61103 /**
@@ -65,7 +107,7 @@ public F2<A, A, Boolean> eq() {
65107 * @return A function that returns <code>true</code> if the given argument equals the argument to this method.
66108 */
67109 public F <A , Boolean > eq (final A a ) {
68- return f . f (a );
110+ return def . equal (a );
69111 }
70112
71113 /**
@@ -75,7 +117,18 @@ public F<A, Boolean> eq(final A a) {
75117 * @return A new equal.
76118 */
77119 public <B > Equal <B > contramap (final F <B , A > f ) {
78- return equal (F1Functions .o (F1Functions .o (F1Functions .andThen (f ), this .f ), f ));
120+ Definition <A > eaDef = def ;
121+ return equalDef (new Definition <B >(){
122+ @ Override
123+ public F <B , Boolean > equal (B b ) {
124+ return compose (eaDef .equal (f .f (b )), f );
125+ }
126+
127+ @ Override
128+ public boolean equal (B b1 , B b2 ) {
129+ return eaDef .equal (f .f (b1 ), f .f (b2 ));
130+ }
131+ });
79132 }
80133
81134 /**
@@ -85,7 +138,27 @@ public <B> Equal<B> contramap(final F<B, A> f) {
85138 * @return An equal instance from the given function.
86139 */
87140 public static <A > Equal <A > equal (final F <A , F <A , Boolean >> f ) {
88- return new Equal <>(f );
141+ return new Equal <>(f ::f );
142+ }
143+
144+ /**
145+ * Constructs an equal instance from the given definition.
146+ *
147+ * @param definition The minimal definition of the equal instance.
148+ * @return An equal instance from the given function.
149+ */
150+ public static <A > Equal <A > equalDef (final Definition <A > definition ) {
151+ return new Equal <>(definition );
152+ }
153+
154+ /**
155+ * Constructs an equal instance from the given definition.
156+ *
157+ * @param definition The minimal definition of the equal instance.
158+ * @return An equal instance from the given function.
159+ */
160+ public static <A > Equal <A > equalAltDef (final AlternateDefinition <A > definition ) {
161+ return new Equal <>(definition );
89162 }
90163
91164 /**
@@ -96,7 +169,17 @@ public static <A> Equal<A> equal(final F<A, F<A, Boolean>> f) {
96169 * equality.
97170 */
98171 public static <A > Equal <A > anyEqual () {
99- return equal (a1 -> a1 ::equals );
172+ return equalDef (new Definition <A >() {
173+ @ Override
174+ public F <A , Boolean > equal (A a ) {
175+ return a ::equals ;
176+ }
177+
178+ @ Override
179+ public boolean equal (A a1 , A a2 ) {
180+ return a1 .equals (a2 );
181+ }
182+ });
100183 }
101184
102185 /**
@@ -163,7 +246,7 @@ public static <A> Equal<A> anyEqual() {
163246 * An equal instance for the {@link StringBuffer} type.
164247 */
165248 public static final Equal <StringBuffer > stringBufferEqual =
166- equal ( sb1 -> sb2 -> {
249+ equalAltDef (( sb1 , sb2 ) -> {
167250 if (sb1 .length () == sb2 .length ()) {
168251 for (int i = 0 ; i < sb1 .length (); i ++)
169252 if (sb1 .charAt (i ) != sb2 .charAt (i ))
@@ -177,7 +260,7 @@ public static <A> Equal<A> anyEqual() {
177260 * An equal instance for the {@link StringBuilder} type.
178261 */
179262 public static final Equal <StringBuilder > stringBuilderEqual =
180- equal ( sb1 -> sb2 -> {
263+ equalAltDef (( sb1 , sb2 ) -> {
181264 if (sb1 .length () == sb2 .length ()) {
182265 for (int i = 0 ; i < sb1 .length (); i ++)
183266 if (sb1 .charAt (i ) != sb2 .charAt (i ))
@@ -195,8 +278,12 @@ public static <A> Equal<A> anyEqual() {
195278 * @return An equal instance for the {@link Either} type.
196279 */
197280 public static <A , B > Equal <Either <A , B >> eitherEqual (final Equal <A > ea , final Equal <B > eb ) {
198- return equal (e1 -> e2 -> e1 .isLeft () && e2 .isLeft () && ea .f .f (e1 .left ().value ()).f (e2 .left ().value ()) ||
199- e1 .isRight () && e2 .isRight () && eb .f .f (e1 .right ().value ()).f (e2 .right ().value ()));
281+ Definition <A > eaDef = ea .def ;
282+ Definition <B > ebDef = eb .def ;
283+ return equalDef (e1 -> e1 .either (
284+ a1 -> Either .cata (eaDef .equal (a1 ), (B __ ) -> false ),
285+ b1 -> Either .cata ((A __ )-> false , ebDef .equal (b1 ))
286+ ));
200287 }
201288
202289 /**
@@ -217,12 +304,13 @@ public static <A, B> Equal<Validation<A, B>> validationEqual(final Equal<A> ea,
217304 * @return An equal instance for the {@link List} type.
218305 */
219306 public static <A > Equal <List <A >> listEqual (final Equal <A > ea ) {
220- return equal (a1 -> a2 -> {
307+ Definition <A > eaDef = ea .def ;
308+ return equalAltDef ((a1 , a2 ) -> {
221309 List <A > x1 = a1 ;
222310 List <A > x2 = a2 ;
223311
224312 while (x1 .isNotEmpty () && x2 .isNotEmpty ()) {
225- if (!ea . eq (x1 .head (), x2 .head ()))
313+ if (!eaDef . equal (x1 .head (), x2 .head ()))
226314 return false ;
227315
228316 x1 = x1 .tail ();
@@ -250,12 +338,15 @@ public static <A> Equal<NonEmptyList<A>> nonEmptyListEqual(final Equal<A> ea) {
250338 * @return An equal instance for the {@link Option} type.
251339 */
252340 public static <A > Equal <Option <A >> optionEqual (final Equal <A > ea ) {
253- return equal (o1 -> o2 -> o1 .isNone () && o2 .isNone () ||
254- o1 .isSome () && o2 .isSome () && ea .f .f (o1 .some ()).f (o2 .some ()));
341+ Definition <A > eaDef = ea .def ;
342+ return equalDef (o1 -> o1 .option (
343+ Option .isNone_ (),
344+ a1 -> Option .cata (false , eaDef .equal (a1 ))
345+ ));
255346 }
256347
257348 public static <A > Equal <Seq <A >> seqEqual (final Equal <A > e ) {
258- return equal ( s1 -> s2 -> streamEqual (e ).eq ( s1 . toStream (), s2 . toStream ()) );
349+ return streamEqual (e ).contramap ( Seq :: toStream );
259350 }
260351
261352 /**
@@ -265,12 +356,13 @@ public static <A> Equal<Seq<A>> seqEqual(final Equal<A> e) {
265356 * @return An equal instance for the {@link Stream} type.
266357 */
267358 public static <A > Equal <Stream <A >> streamEqual (final Equal <A > ea ) {
268- return equal (a1 -> a2 -> {
359+ Definition <A > eaDef = ea .def ;
360+ return equalAltDef ((a1 , a2 ) -> {
269361 Stream <A > x1 = a1 ;
270362 Stream <A > x2 = a2 ;
271363
272364 while (x1 .isNotEmpty () && x2 .isNotEmpty ()) {
273- if (!ea . eq (x1 .head (), x2 .head ()))
365+ if (!eaDef . equal (x1 .head (), x2 .head ()))
274366 return false ;
275367
276368 x1 = x1 .tail ()._1 ();
@@ -288,10 +380,11 @@ public static <A> Equal<Stream<A>> streamEqual(final Equal<A> ea) {
288380 * @return An equal instance for the {@link Array} type.
289381 */
290382 public static <A > Equal <Array <A >> arrayEqual (final Equal <A > ea ) {
291- return equal (a1 -> a2 -> {
383+ Definition <A > eaDef = ea .def ;
384+ return equalAltDef ((a1 , a2 ) -> {
292385 if (a1 .length () == a2 .length ()) {
293386 for (int i = 0 ; i < a1 .length (); i ++) {
294- if (!ea . eq (a1 .get (i ), a2 .get (i )))
387+ if (!eaDef . equal (a1 .get (i ), a2 .get (i )))
295388 return false ;
296389 }
297390 return true ;
@@ -307,7 +400,7 @@ public static <A> Equal<Array<A>> arrayEqual(final Equal<A> ea) {
307400 * @return An equal instance for the {@link Tree} type.
308401 */
309402 public static <A > Equal <Tree <A >> treeEqual (final Equal <A > ea ) {
310- return Equal . equal ( curry (( t1 , t2 ) -> ea .eq (t1 .root (), t2 .root ()) && p1Equal (streamEqual (Equal . treeEqual (ea ))).eq (t2 .subForest (), t1 .subForest () )));
403+ return equalAltDef (( t1 , t2 ) -> ea .eq (t1 .root (), t2 .root ()) && p1Equal (streamEqual (treeEqual (ea ))).eq (t2 .subForest (), t1 .subForest ()));
311404 }
312405
313406 /**
@@ -317,7 +410,7 @@ public static <A> Equal<Tree<A>> treeEqual(final Equal<A> ea) {
317410 * @return An equal instance for a product-1.
318411 */
319412 public static <A > Equal <P1 <A >> p1Equal (final Equal <A > ea ) {
320- return equal ( p1 -> p2 -> ea .eq (p1 ._1 (), p2 ._1 ()));
413+ return equalAltDef (( p1 , p2 ) -> ea .eq (p1 ._1 (), p2 ._1 ()));
321414 }
322415
323416 /**
@@ -328,7 +421,7 @@ public static <A> Equal<P1<A>> p1Equal(final Equal<A> ea) {
328421 * @return An equal instance for a product-2.
329422 */
330423 public static <A , B > Equal <P2 <A , B >> p2Equal (final Equal <A > ea , final Equal <B > eb ) {
331- return equal ( p1 -> p2 -> ea .eq (p1 ._1 (), p2 ._1 ()) && eb .eq (p1 ._2 (), p2 ._2 ()));
424+ return equalAltDef (( p1 , p2 ) -> ea .eq (p1 ._1 (), p2 ._1 ()) && eb .eq (p1 ._2 (), p2 ._2 ()));
332425 }
333426
334427 /**
@@ -340,7 +433,7 @@ public static <A, B> Equal<P2<A, B>> p2Equal(final Equal<A> ea, final Equal<B> e
340433 * @return An equal instance for a product-3.
341434 */
342435 public static <A , B , C > Equal <P3 <A , B , C >> p3Equal (final Equal <A > ea , final Equal <B > eb , final Equal <C > ec ) {
343- return equal ( p1 -> p2 -> ea .eq (p1 ._1 (), p2 ._1 ()) && eb .eq (p1 ._2 (), p2 ._2 ()) && ec .eq (p1 ._3 (), p2 ._3 ()));
436+ return equalAltDef (( p1 , p2 ) -> ea .eq (p1 ._1 (), p2 ._1 ()) && eb .eq (p1 ._2 (), p2 ._2 ()) && ec .eq (p1 ._3 (), p2 ._3 ()));
344437 }
345438
346439 /**
@@ -354,7 +447,7 @@ public static <A, B, C> Equal<P3<A, B, C>> p3Equal(final Equal<A> ea, final Equa
354447 */
355448 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 ,
356449 final Equal <D > ed ) {
357- return equal ( p1 -> p2 -> ea .eq (p1 ._1 (), p2 ._1 ()) && eb .eq (p1 ._2 (), p2 ._2 ()) && ec .eq (p1 ._3 (), p2 ._3 ()) &&
450+ return equalAltDef (( p1 , p2 ) -> ea .eq (p1 ._1 (), p2 ._1 ()) && eb .eq (p1 ._2 (), p2 ._2 ()) && ec .eq (p1 ._3 (), p2 ._3 ()) &&
358451 ed .eq (p1 ._4 (), p2 ._4 ()));
359452 }
360453
@@ -371,7 +464,7 @@ public static <A, B, C, D> Equal<P4<A, B, C, D>> p4Equal(final Equal<A> ea, fina
371464 public static <A , B , C , D , E > Equal <P5 <A , B , C , D , E >> p5Equal (final Equal <A > ea , final Equal <B > eb ,
372465 final Equal <C > ec , final Equal <D > ed ,
373466 final Equal <E > ee ) {
374- return equal ( p1 -> p2 -> ea .eq (p1 ._1 (), p2 ._1 ()) && eb .eq (p1 ._2 (), p2 ._2 ()) && ec .eq (p1 ._3 (), p2 ._3 ()) &&
467+ return equalAltDef (( p1 , p2 ) -> ea .eq (p1 ._1 (), p2 ._1 ()) && eb .eq (p1 ._2 (), p2 ._2 ()) && ec .eq (p1 ._3 (), p2 ._3 ()) &&
375468 ed .eq (p1 ._4 (), p2 ._4 ()) && ee .eq (p1 ._5 (), p2 ._5 ()));
376469 }
377470
@@ -389,7 +482,7 @@ public static <A, B, C, D, E> Equal<P5<A, B, C, D, E>> p5Equal(final Equal<A> ea
389482 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 ,
390483 final Equal <C > ec , final Equal <D > ed ,
391484 final Equal <E > ee , final Equal <F$ > ef ) {
392- return equal ( p1 -> p2 -> ea .eq (p1 ._1 (), p2 ._1 ()) && eb .eq (p1 ._2 (), p2 ._2 ()) && ec .eq (p1 ._3 (), p2 ._3 ()) &&
485+ return equalAltDef (( p1 , p2 ) -> ea .eq (p1 ._1 (), p2 ._1 ()) && eb .eq (p1 ._2 (), p2 ._2 ()) && ec .eq (p1 ._3 (), p2 ._3 ()) &&
393486 ed .eq (p1 ._4 (), p2 ._4 ()) && ee .eq (p1 ._5 (), p2 ._5 ()) && ef .eq (p1 ._6 (), p2 ._6 ()));
394487 }
395488
@@ -409,7 +502,7 @@ public static <A, B, C, D, E> Equal<P5<A, B, C, D, E>> p5Equal(final Equal<A> ea
409502 final Equal <C > ec , final Equal <D > ed ,
410503 final Equal <E > ee , final Equal <F$ > ef ,
411504 final Equal <G > eg ) {
412- return equal ( p1 -> p2 -> ea .eq (p1 ._1 (), p2 ._1 ()) && eb .eq (p1 ._2 (), p2 ._2 ()) && ec .eq (p1 ._3 (), p2 ._3 ()) &&
505+ return equalAltDef (( p1 , p2 ) -> ea .eq (p1 ._1 (), p2 ._1 ()) && eb .eq (p1 ._2 (), p2 ._2 ()) && ec .eq (p1 ._3 (), p2 ._3 ()) &&
413506 ed .eq (p1 ._4 (), p2 ._4 ()) && ee .eq (p1 ._5 (), p2 ._5 ()) && ef .eq (p1 ._6 (), p2 ._6 ()) &&
414507 eg .eq (p1 ._7 (), p2 ._7 ()));
415508 }
@@ -435,8 +528,8 @@ public static <A, B, C, D, E> Equal<P5<A, B, C, D, E>> p5Equal(final Equal<A> ea
435528 final Equal <F$ > ef ,
436529 final Equal <G > eg ,
437530 final Equal <H > eh ) {
438- return equal (
439- p1 -> p2 -> ea .eq (p1 ._1 (), p2 ._1 ()) && eb .eq (p1 ._2 (), p2 ._2 ()) && ec .eq (p1 ._3 (), p2 ._3 ()) &&
531+ return equalAltDef (
532+ ( p1 , p2 ) -> ea .eq (p1 ._1 (), p2 ._1 ()) && eb .eq (p1 ._2 (), p2 ._2 ()) && ec .eq (p1 ._3 (), p2 ._3 ()) &&
440533 ed .eq (p1 ._4 (), p2 ._4 ()) && ee .eq (p1 ._5 (), p2 ._5 ()) && ef .eq (p1 ._6 (), p2 ._6 ()) &&
441534 eg .eq (p1 ._7 (), p2 ._7 ()) && eh .eq (p1 ._8 (), p2 ._8 ()));
442535 }
0 commit comments