1616
1717import static fj .Function .apply ;
1818import static fj .Function .compose ;
19+ import static fj .Function .compose2 ;
1920import static fj .Function .curry ;
2021import static fj .Semigroup .semigroup ;
2122
2526 * @version %build.number%
2627 */
2728public final class Ord <A > {
28- private final F <A , F <A , Ordering >> f ;
2929
30- private Ord (final F <A , F <A , Ordering >> f ) {
31- this .f = f ;
32- this .max = a1 -> apply ((a2 , o ) -> o == Ordering .GT ? a1 : a2 , f .f (a1 ));
33- this .min = a1 -> apply ((a2 , o ) -> o == Ordering .LT ? a1 : a2 , f .f (a1 ));
30+ /**
31+ * Primitives functions of Ord: minimal definition and overridable methods.
32+ */
33+ public interface Definition <A > extends Equal .Definition <A > {
34+
35+ F <A , Ordering > compare (A a );
36+
37+ default Ordering compare (A a1 , A a2 ) {
38+ return compare (a1 ).f (a2 );
39+ }
40+
41+ @ Override
42+ default boolean equal (A a1 , A a2 ) {
43+ return compare (a1 , a2 ) == Ordering .EQ ;
44+ }
45+
46+ @ Override
47+ default F <A , Boolean > equal (A a ) {
48+ return compose (o -> o == Ordering .EQ , compare (a ));
49+ }
50+ }
51+
52+ /**
53+ * Primitives functions of Ord: alternative minimal definition and overridable methods.
54+ */
55+ public interface AlternateDefinition <A > extends Definition <A > {
56+
57+ Ordering compare (A a1 , A a2 );
58+
59+ default F <A , Ordering > compare (A a1 ) {
60+ return a2 -> compare (a1 , a2 );
61+ }
62+
63+ }
64+
65+
66+ private final Definition <A > def ;
67+
68+ private Ord (final Definition <A > def ) {
69+ this .def = def ;
70+ this .max = a1 -> apply ((a2 , o ) -> o == Ordering .GT ? a1 : a2 , def .compare (a1 ));
71+ this .min = a1 -> apply ((a2 , o ) -> o == Ordering .LT ? a1 : a2 , def .compare (a1 ));
3472 }
3573
3674 /**
@@ -39,7 +77,7 @@ private Ord(final F<A, F<A, Ordering>> f) {
3977 * @return A function that returns an ordering for its arguments.
4078 */
4179 public F <A , F <A , Ordering >> compare () {
42- return f ;
80+ return def :: compare ;
4381 }
4482
4583 /**
@@ -50,7 +88,7 @@ public F<A, F<A, Ordering>> compare() {
5088 * @return An ordering for the given arguments.
5189 */
5290 public Ordering compare (final A a1 , final A a2 ) {
53- return f . f (a1 ). f ( a2 );
91+ return def . compare (a1 , a2 );
5492 }
5593
5694 /**
@@ -61,7 +99,7 @@ public Ordering compare(final A a1, final A a2) {
6199 * @return <code>true</code> if the given arguments are equal, <code>false</code> otherwise.
62100 */
63101 public boolean eq (final A a1 , final A a2 ) {
64- return compare (a1 , a2 ) == Ordering .EQ ;
102+ return def . compare (a1 , a2 ) == Ordering .EQ ;
65103 }
66104
67105 /**
@@ -70,7 +108,7 @@ public boolean eq(final A a1, final A a2) {
70108 * @return An <code>Equal</code> for this order.
71109 */
72110 public Equal <A > equal () {
73- return Equal .equal ( a -> compose ( o -> o == Ordering . EQ , f . f ( a )) );
111+ return Equal .equalDef ( def );
74112 }
75113
76114 /**
@@ -80,7 +118,18 @@ public Equal<A> equal() {
80118 * @return A new ord.
81119 */
82120 public <B > Ord <B > contramap (final F <B , A > f ) {
83- return ord (F1Functions .o (F1Functions .o (F1Functions .andThen (f ), this .f ), f ));
121+ Definition <A > selfDef = def ;
122+ return ordDef (new Definition <B >() {
123+ @ Override
124+ public F <B , Ordering > compare (B b ) {
125+ return compose (selfDef .compare (f .f (b )), f );
126+ }
127+
128+ @ Override
129+ public Ordering compare (B b1 , B b2 ) {
130+ return selfDef .compare (f .f (b1 ), f .f (b2 ));
131+ }
132+ });
84133 }
85134
86135 /**
@@ -93,7 +142,7 @@ public <B> Ord<B> contramap(final F<B, A> f) {
93142 * <code>false</code> otherwise.
94143 */
95144 public boolean isLessThan (final A a1 , final A a2 ) {
96- return compare (a1 , a2 ) == Ordering .LT ;
145+ return def . compare (a1 , a2 ) == Ordering .LT ;
97146 }
98147
99148 /**
@@ -106,7 +155,7 @@ public boolean isLessThan(final A a1, final A a2) {
106155 * <code>false</code> otherwise.
107156 */
108157 public boolean isLessThanOrEqualTo (final A a1 , final A a2 ) {
109- return compare (a1 , a2 ) != Ordering .GT ;
158+ return def . compare (a1 , a2 ) != Ordering .GT ;
110159 }
111160
112161 /**
@@ -119,7 +168,7 @@ public boolean isLessThanOrEqualTo(final A a1, final A a2) {
119168 * argument, <code>false</code> otherwise.
120169 */
121170 public boolean isGreaterThan (final A a1 , final A a2 ) {
122- return compare (a1 , a2 ) == Ordering .GT ;
171+ return def . compare (a1 , a2 ) == Ordering .GT ;
123172 }
124173
125174 /**
@@ -129,7 +178,7 @@ public boolean isGreaterThan(final A a1, final A a2) {
129178 * @return A function that returns true if its argument is less than the argument to this method.
130179 */
131180 public F <A , Boolean > isLessThan (final A a ) {
132- return compose (o -> o != Ordering .LT , f . f (a ));
181+ return compose (o -> o != Ordering .LT , def . compare (a ));
133182 }
134183
135184 /**
@@ -139,7 +188,7 @@ public F<A, Boolean> isLessThan(final A a) {
139188 * @return A function that returns true if its argument is greater than the argument to this method.
140189 */
141190 public F <A , Boolean > isGreaterThan (final A a ) {
142- return compose (o -> o != Ordering .GT , f . f (a ));
191+ return compose (o -> o != Ordering .GT , def . compare (a ));
143192 }
144193
145194 /**
@@ -183,7 +232,20 @@ public final Semigroup<A> maxSemigroup() {
183232 return semigroup (max );
184233 }
185234
186- public final Ord <A > reverse () { return ord (Function .flip (f )); }
235+ public final Ord <A > reverse () {
236+ Definition <A > selfDef = def ;
237+ return ordDef (new Definition <A >() {
238+ @ Override
239+ public F <A , Ordering > compare (A a ) {
240+ return compose (Ordering ::reverse , selfDef .compare (a ));
241+ }
242+
243+ @ Override
244+ public Ordering compare (A a1 , A a2 ) {
245+ return selfDef .compare (a2 , a1 );
246+ }
247+ });
248+ }
187249
188250 /**
189251 * Returns an order instance that uses the given equality test and ordering function.
@@ -192,9 +254,30 @@ public final Semigroup<A> maxSemigroup() {
192254 * @return An order instance.
193255 */
194256 public static <A > Ord <A > ord (final F <A , F <A , Ordering >> f ) {
195- return new Ord <>(f );
257+ return new Ord <>(f :: f );
196258 }
197259
260+ /**
261+ * Returns an order instance that uses the given minimal equality test and ordering definiion.
262+ *
263+ * @param def The order definition.
264+ * @return An order instance.
265+ */
266+ public static <A > Ord <A > ordDef (final Definition <A > def ) {
267+ return new Ord <>(def );
268+ }
269+
270+ /**
271+ * Returns an order instance that uses the given minimal equality test and ordering definiion.
272+ *
273+ * @param def The order definition.
274+ * @return An order instance.
275+ */
276+ public static <A > Ord <A > ordDef (final AlternateDefinition <A > def ) {
277+ return new Ord <>(def );
278+ }
279+
280+
198281 /**
199282 * An order instance for the <code>boolean</code> type.
200283 */
@@ -248,15 +331,15 @@ public static <A> Ord<A> ord(final F<A, F<A, Ordering>> f) {
248331 /**
249332 * An order instance for the {@link Ordering} type.
250333 */
251- public static final Ord <Ordering > orderingOrd = Ord . ord ( curry ((o1 , o2 ) -> o1 == o2 ?
334+ public static final Ord <Ordering > orderingOrd = ordDef ((o1 , o2 ) -> o1 == o2 ?
252335 Ordering .EQ :
253336 o1 == Ordering .LT ?
254337 Ordering .LT :
255338 o2 == Ordering .LT ?
256339 Ordering .GT :
257340 o1 == Ordering .EQ ?
258341 Ordering .LT :
259- Ordering .GT )) ;
342+ Ordering .GT );
260343
261344 /**
262345 * An order instance for the {@link String} type.
@@ -280,13 +363,14 @@ public static <A> Ord<A> ord(final F<A, F<A, Ordering>> f) {
280363 * @return An order instance for the {@link Option} type.
281364 */
282365 public static <A > Ord <Option <A >> optionOrd (final Ord <A > oa ) {
283- return ord (o1 -> o2 -> o1 .isNone () ?
366+ Definition <A > oaDef = oa .def ;
367+ return ordDef ((o1 , o2 ) -> o1 .isNone () ?
284368 o2 .isNone () ?
285369 Ordering .EQ :
286370 Ordering .LT :
287371 o2 .isNone () ?
288372 Ordering .GT :
289- oa . f . f (o1 .some ()).f (o2 .some ()));
373+ oaDef . compare (o1 .some ()).f (o2 .some ()));
290374 }
291375
292376 /**
@@ -297,13 +381,15 @@ public static <A> Ord<Option<A>> optionOrd(final Ord<A> oa) {
297381 * @return An order instance for the {@link Either} type.
298382 */
299383 public static <A , B > Ord <Either <A , B >> eitherOrd (final Ord <A > oa , final Ord <B > ob ) {
300- return ord (e1 -> e2 -> e1 .isLeft () ?
384+ Definition <A > oaDef = oa .def ;
385+ Definition <B > obDef = ob .def ;
386+ return ordDef ((e1 , e2 ) -> e1 .isLeft () ?
301387 e2 .isLeft () ?
302- oa . f . f (e1 .left ().value ()).f (e2 .left ().value ()) :
303- Ordering .LT :
388+ oaDef . compare (e1 .left ().value ()).f (e2 .left ().value ()) :
389+ Ordering .LT :
304390 e2 .isLeft () ?
305- Ordering .GT :
306- ob . f . f (e1 .right ().value ()).f (e2 .right ().value ()));
391+ Ordering .GT :
392+ obDef . compare (e1 .right ().value ()).f (e2 .right ().value ()));
307393 }
308394
309395 /**
@@ -324,7 +410,7 @@ public static <A, B> Ord<Validation<A, B>> validationOrd(final Ord<A> oa, final
324410 * @return An order instance for the {@link List} type.
325411 */
326412 public static <A > Ord <List <A >> listOrd (final Ord <A > oa ) {
327- return ord ( l1 -> l2 -> {
413+ return ordDef (( l1 , l2 ) -> {
328414 List <A > x1 = l1 ;
329415 List <A > x2 = l2 ;
330416
@@ -364,14 +450,15 @@ public static <A> Ord<NonEmptyList<A>> nonEmptyListOrd(final Ord<A> oa) {
364450 * @return An order instance for the {@link Stream} type.
365451 */
366452 public static <A > Ord <Stream <A >> streamOrd (final Ord <A > oa ) {
367- return ord ( s1 -> s2 -> {
453+ return ordDef (( s1 , s2 ) -> {
368454 if (s1 .isEmpty ())
369455 return s2 .isEmpty () ? Ordering .EQ : Ordering .LT ;
370456 else if (s2 .isEmpty ())
371457 return s1 .isEmpty () ? Ordering .EQ : Ordering .GT ;
372458 else {
373459 final Ordering c = oa .compare (s1 .head (), s2 .head ());
374- return c == Ordering .EQ ? streamOrd (oa ).f .f (s1 .tail ()._1 ()).f (s2 .tail ()._1 ()) : c ;
460+ // FIXME: not stack safe
461+ return c == Ordering .EQ ? streamOrd (oa ).def .compare (s1 .tail ()._1 ()).f (s2 .tail ()._1 ()) : c ;
375462 }
376463 });
377464 }
@@ -383,7 +470,7 @@ else if (s2.isEmpty())
383470 * @return An order instance for the {@link Array} type.
384471 */
385472 public static <A > Ord <Array <A >> arrayOrd (final Ord <A > oa ) {
386- return ord ( a1 -> a2 -> {
473+ return ordDef (( a1 , a2 ) -> {
387474 int i = 0 ;
388475 //noinspection ForLoopWithMissingComponent
389476 for (; i < a1 .length () && i < a2 .length (); i ++) {
@@ -414,7 +501,7 @@ public static <A> Ord<Set<A>> setOrd(final Ord<A> oa) {
414501 /**
415502 * An order instance for the {@link Unit} type.
416503 */
417- public static final Ord <Unit > unitOrd = ord ( curry (( Unit u1 , Unit u2 ) -> Ordering .EQ ) );
504+ public static final Ord <Unit > unitOrd = ordDef (( u1 , u2 ) -> Ordering .EQ );
418505
419506 /**
420507 * An order instance for a product-1.
@@ -435,15 +522,15 @@ public static <A> Ord<P1<A>> p1Ord(final Ord<A> oa) {
435522 * @return An order instance for a product-2, with the first factor considered most significant.
436523 */
437524 public static <A , B > Ord <P2 <A , B >> p2Ord (final Ord <A > oa , final Ord <B > ob ) {
438- return ord ( curry (( P2 < A , B > a , P2 < A , B > b ) -> oa .eq (a ._1 (), b ._1 ()) ? ob .compare (a ._2 (), b ._2 ()) : oa .compare (a ._1 (), b ._1 () )));
525+ return ordDef (( a , b ) -> oa .eq (a ._1 (), b ._1 ()) ? ob .compare (a ._2 (), b ._2 ()) : oa .compare (a ._1 (), b ._1 ()));
439526 }
440527
441528 public static <A , B > Ord <P2 <A , B >> p2Ord1 (Ord <A > oa ) {
442- return ord ( p1 -> p2 -> oa .compare (p1 ._1 (), p2 ._1 ()));
529+ return ordDef (( p1 , p2 ) -> oa .compare (p1 ._1 (), p2 ._1 ()));
443530 }
444531
445532 public static <A , B > Ord <P2 <A , B >> p2Ord2 (Ord <B > ob ) {
446- return ord ( p1 -> p2 -> ob .compare (p1 ._2 (), p2 ._2 ()));
533+ return ordDef (( p1 , p2 ) -> ob .compare (p1 ._2 (), p2 ._2 ()));
447534 }
448535
449536 /**
@@ -455,9 +542,9 @@ public static <A, B> Ord<P2<A, B>> p2Ord2(Ord<B> ob) {
455542 * @return An order instance for a product-3, with the first factor considered most significant.
456543 */
457544 public static <A , B , C > Ord <P3 <A , B , C >> p3Ord (final Ord <A > oa , final Ord <B > ob , final Ord <C > oc ) {
458- return ord ( curry (( P3 < A , B , C > a , P3 < A , B , C > b ) -> oa .eq (a ._1 (), b ._1 ()) ?
545+ return ordDef (( a , b ) -> oa .eq (a ._1 (), b ._1 ()) ?
459546 p2Ord (ob , oc ).compare (P .p (a ._2 (), a ._3 ()), P .p (b ._2 (), b ._3 ()))
460- : oa .compare (a ._1 (), b ._1 ()))) ;
547+ : oa .compare (a ._1 (), b ._1 ()));
461548 }
462549
463550 /**
@@ -472,8 +559,7 @@ public static <A, B, C> Ord<P3<A, B, C>> p3Ord(final Ord<A> oa, final Ord<B> ob,
472559 * @return An order instance for the <code>Comparable</code> interface.
473560 */
474561 public static <A extends Comparable <A >> Ord <A > comparableOrd () {
475-
476- return ord (a1 -> a2 -> Ordering .fromInt (a1 .compareTo (a2 )));
562+ return ordDef ((a1 , a2 ) -> Ordering .fromInt (a1 .compareTo (a2 )));
477563 }
478564
479565 /**
@@ -485,7 +571,7 @@ public static <A extends Comparable<A>> Ord<A> comparableOrd() {
485571 * @see #hashEqualsOrd()
486572 */
487573 public static <A > Ord <A > hashOrd () {
488- return ord (a -> {
574+ return ordDef (a -> {
489575 int aHash = a .hashCode ();
490576 return a2 -> Ordering .fromInt (Integer .compare (aHash , a2 .hashCode ()));
491577 });
@@ -499,7 +585,7 @@ public static <A> Ord<A> hashOrd() {
499585 * @return An order instance that is based on {@link Object#hashCode()} and {@link Object#equals}.
500586 */
501587 public static <A > Ord <A > hashEqualsOrd () {
502- return ord (a -> {
588+ return ordDef (a -> {
503589 int aHash = a .hashCode ();
504590 return a2 -> {
505591 final int a2Hash = a2 .hashCode ();
0 commit comments