@@ -84,6 +84,42 @@ public Definition<A> dual() {
8484 }
8585 };
8686 }
87+
88+ /**
89+ * Refine this ord definition: compares using self and if objects are equal compares using given <code>Ord</code>.
90+ * @see #ord()
91+ *
92+ * @param bOrd Ord for subsequent comparison
93+ * @return A new ord definition.
94+ */
95+ default <B > Definition <A > then (final F <A , B > f , final Ord <B > bOrd ) {
96+ Definition <B > bOrdDef = bOrd .def ;
97+ return new Definition <A >() {
98+ @ Override
99+ public F <A , Ordering > compare (A a1 ) {
100+ F <A , Ordering > fa = Definition .this .compare (a1 );
101+ F <B , Ordering > fb = bOrdDef .compare (f .f (a1 ));
102+ return a2 -> {
103+ Ordering aOrdering = fa .f (a2 );
104+ return aOrdering != Ordering .EQ ? aOrdering : fb .f (f .f (a2 ));
105+ };
106+ }
107+
108+ @ Override
109+ public Ordering compare (A a1 , A a2 ) {
110+ Ordering aOrdering = Definition .this .compare (a1 , a2 );
111+ return aOrdering != Ordering .EQ ? aOrdering : bOrdDef .compare (f .f (a1 ), f .f (a2 ));
112+ }
113+ };
114+ }
115+
116+ /**
117+ * Build an ord instance from this definition.
118+ * to be called after some successive {@link #then(F, Ord)} calls.
119+ */
120+ default Ord <A > ord () {
121+ return ordDef (this );
122+ }
87123 }
88124
89125 /**
@@ -160,18 +196,7 @@ public Equal<A> equal() {
160196 * @return A new ord.
161197 */
162198 public <B > Ord <B > contramap (final F <B , A > f ) {
163- Definition <A > selfDef = def ;
164- return ordDef (new Definition <B >() {
165- @ Override
166- public F <B , Ordering > compare (B b ) {
167- return compose (selfDef .compare (f .f (b )), f );
168- }
169-
170- @ Override
171- public Ordering compare (B b1 , B b2 ) {
172- return selfDef .compare (f .f (b1 ), f .f (b2 ));
173- }
174- });
199+ return ordDef (contramapDef (f , def ));
175200 }
176201
177202 /**
@@ -288,36 +313,32 @@ public final Ord<A> reverse() {
288313 }
289314
290315 /**
291- * Constructs an ord instance, which compares using self and if objects are equal compares using <code>ord</code>
292- *
293- * @param ord Ord for subsequent comparison
294- * @return A new equal instance
316+ * Begin definition of an ord instance.
317+ * @see Definition#then(F, Equal)
295318 */
296- public final Ord <A > andThen (final Ord <A > ord ) {
297- return ordDef ((a1 , a2 ) -> {
298- final Ordering compareResult = compare (a1 , a2 );
299- if (compareResult == Ordering .EQ )
300- return ord .compare (a1 , a2 );
301- return compareResult ;
302- });
303- }
304-
305- /**
306- * Constructs an ord instance, which compares using self and if objects are equal compares the mapped objects
307- *
308- * @param f The function to map the original object
309- * @param ord Ord for the mapped object
310- * @return A new equal instance
311- */
312- public final <B > Ord <A > andThen (final F <A , B > f , final Ord <B > ord ) {
313- return andThen (ord .contramap (f ));
319+ public static <A , B > Definition <A > on (final F <A , B > f , final Ord <B > ord ) {
320+ return contramapDef (f , ord .def );
314321 }
315322
316323 /**
317324 * Static version of {@link #contramap(F)}
318325 */
319326 public static <A , B > Ord <A > contramap (final F <A , B > f , final Ord <B > ord ) {
320- return ord .contramap (f );
327+ return ordDef (contramapDef (f , ord .def ));
328+ }
329+
330+ private static <A , B > Definition <B > contramapDef (F <B , A > f , Definition <A > def ) {
331+ return new Definition <B >() {
332+ @ Override
333+ public F <B , Ordering > compare (B b ) {
334+ return compose (def .compare (f .f (b )), f );
335+ }
336+
337+ @ Override
338+ public Ordering compare (B b1 , B b2 ) {
339+ return def .compare (f .f (b1 ), f .f (b2 ));
340+ }
341+ };
321342 }
322343
323344 /**
@@ -609,15 +630,15 @@ public static <A> Ord<P1<A>> p1Ord(final Ord<A> oa) {
609630 * @return An order instance for a product-2, with the first factor considered most significant.
610631 */
611632 public static <A , B > Ord <P2 <A , B >> p2Ord (final Ord <A > oa , final Ord <B > ob ) {
612- return ordDef (( a , b ) -> oa . eq ( a . _1 ( ), b . _1 ()) ? ob . compare ( a . _2 (), b . _2 ()) : oa . compare ( a . _1 (), b . _1 ()) );
633+ return on ( P2 .< A , B > __1 ( ), oa ). then ( P2 . __2 (), ob ). ord ( );
613634 }
614635
615636 public static <A , B > Ord <P2 <A , B >> p2Ord1 (Ord <A > oa ) {
616- return ordDef (( p1 , p2 ) -> oa . compare ( p1 . _1 ( ), p2 . _1 ()) );
637+ return on ( P2 .< A , B > __1 ( ), oa ). ord ( );
617638 }
618639
619640 public static <A , B > Ord <P2 <A , B >> p2Ord2 (Ord <B > ob ) {
620- return ordDef (( p1 , p2 ) -> ob . compare ( p1 . _2 ( ), p2 . _2 ()) );
641+ return on ( P2 .< A , B > __2 ( ), ob ). ord ( );
621642 }
622643
623644 /**
@@ -629,9 +650,7 @@ public static <A, B> Ord<P2<A, B>> p2Ord2(Ord<B> ob) {
629650 * @return An order instance for a product-3, with the first factor considered most significant.
630651 */
631652 public static <A , B , C > Ord <P3 <A , B , C >> p3Ord (final Ord <A > oa , final Ord <B > ob , final Ord <C > oc ) {
632- return ordDef ((a , b ) -> oa .eq (a ._1 (), b ._1 ()) ?
633- p2Ord (ob , oc ).compare (P .p (a ._2 (), a ._3 ()), P .p (b ._2 (), b ._3 ()))
634- : oa .compare (a ._1 (), b ._1 ()));
653+ return on (P3 .<A , B , C >__1 (), oa ).then (P3 .__2 (), ob ).then (P3 .__3 (), oc ).ord ();
635654 }
636655
637656 /**
0 commit comments