Skip to content

Commit 4a7de0c

Browse files
authored
Merge pull request #279 from mperry/pqueue
Add a priority queue based on finger trees and related changes
2 parents 34534a8 + 24703d5 commit 4a7de0c

File tree

23 files changed

+701
-81
lines changed

23 files changed

+701
-81
lines changed

core/src/main/java/fj/F1Functions.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -670,11 +670,18 @@ public static <A, B> ArrayList<B> mapJ(final F<A, B> f, final ArrayList<A> as) {
670670
}
671671

672672
public static <A, B, C> F<A, C> map(F<A, B> target, F<B, C> f) {
673-
return andThen(target, f);
673+
return o(f, target);
674674
}
675675

676676
public static <A, B, C> F<C, B> contramap(F<A, B> target, F<C, A> f) {
677-
return andThen(f, target);
677+
return o(target, f);
678+
}
679+
680+
/**
681+
* Both map (with g) and contramap (with f) the target function. (Profunctor pattern)
682+
*/
683+
public static <A, B, C, D> F<C, D> dimap(F<A, B> target, F<C, A> f, F<B, D> g) {
684+
return c -> g.f(target.f(f.f(c)));
678685
}
679686

680687
}

core/src/main/java/fj/Function.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,18 @@ public static <A, B, C> F<C, B> bind(final F<C, A> ma, final F<A, F<C, B>> f) {
718718
* @return A new function after applying the given higher-order function to the given function.
719719
*/
720720
public static <A, B, C> F<C, B> apply(final F<C, F<A, B>> cab, final F<C, A> ca) {
721-
return bind(cab, f -> compose(f, ca));
721+
return apply(uncurryF2(cab), ca);
722+
}
723+
724+
/**
725+
* Performs function application within a higher-order function (applicative functor pattern).
726+
*
727+
* @param cab The higher-order function to apply a function to.
728+
* @param ca A function to apply within a higher-order function.
729+
* @return A new function after applying the given higher-order function to the given function.
730+
*/
731+
public static <A, B, C> F<C, B> apply(final F2<C, A, B> cab, final F<C, A> ca) {
732+
return c -> cab.f(c, ca.f(c));
722733
}
723734

724735
/**

core/src/main/java/fj/Monoid.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,16 @@ public static <A> Monoid<IO<A>> ioMonoid(final Monoid <A> ma) {
401401
return monoid(Semigroup.ioSemigroup(ma.semigroup()), IOFunctions.unit(ma.zero()));
402402
}
403403

404+
/**
405+
* A monoid for the maximum of two integers.
406+
*/
407+
public static final Monoid<Integer> intMaxMonoid = monoid(Semigroup.intMaximumSemigroup, Integer.MIN_VALUE);
408+
409+
/**
410+
* A monoid for the minimum of two integers.
411+
*/
412+
public static final Monoid<Integer> intMinMonoid = monoid(Semigroup.intMinimumSemigroup, Integer.MAX_VALUE);
413+
404414
/**
405415
* A monoid for the Unit value.
406416
*/
@@ -416,4 +426,15 @@ public static <A> Monoid<Set<A>> setMonoid(final Ord<A> o) {
416426
return monoid(Semigroup.setSemigroup(), Set.empty(o));
417427
}
418428

429+
430+
/**
431+
* A monoid for the maximum of elements with ordering o.
432+
*
433+
* @param o An ordering of elements.
434+
* @param zero The minimum element.
435+
*/
436+
public static <A> Monoid<A> ordMaxMonoid(final Ord<A> o, final A zero) {
437+
return monoid(o.max, zero);
438+
}
439+
419440
}

core/src/main/java/fj/Ord.java

Lines changed: 46 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
import java.math.BigInteger;
1515
import java.util.Comparator;
1616

17+
import static fj.Function.apply;
18+
import static fj.Function.compose;
1719
import static fj.Function.curry;
1820
import static fj.Semigroup.semigroup;
1921

@@ -27,6 +29,8 @@ public final class Ord<A> {
2729

2830
private Ord(final F<A, F<A, Ordering>> f) {
2931
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));
3034
}
3135

3236
/**
@@ -66,7 +70,7 @@ public boolean eq(final A a1, final A a2) {
6670
* @return An <code>Equal</code> for this order.
6771
*/
6872
public Equal<A> equal() {
69-
return Equal.equal(curry(this::eq));
73+
return Equal.equal(a -> compose(o -> o == Ordering.EQ, f.f(a)));
7074
}
7175

7276
/**
@@ -92,6 +96,19 @@ public boolean isLessThan(final A a1, final A a2) {
9296
return compare(a1, a2) == Ordering.LT;
9397
}
9498

99+
/**
100+
* Returns <code>true</code> if the first given argument is less than or equal to the second given argument,
101+
* <code>false</code> otherwise.
102+
*
103+
* @param a1 An instance to compare for ordering to another.
104+
* @param a2 An instance to compare for ordering to another.
105+
* @return <code>true</code> if the first given argument is less than or equal to the second given argument,
106+
* <code>false</code> otherwise.
107+
*/
108+
public boolean isLessThanOrEqualTo(final A a1, final A a2) {
109+
return compare(a1, a2) != Ordering.GT;
110+
}
111+
95112
/**
96113
* Returns <code>true</code> if the first given argument is greater than the second given
97114
* argument, <code>false</code> otherwise.
@@ -112,7 +129,7 @@ public boolean isGreaterThan(final A a1, final A a2) {
112129
* @return A function that returns true if its argument is less than the argument to this method.
113130
*/
114131
public F<A, Boolean> isLessThan(final A a) {
115-
return a2 -> compare(a2, a) == Ordering.LT;
132+
return compose(o -> o != Ordering.LT, f.f(a));
116133
}
117134

118135
/**
@@ -122,7 +139,7 @@ public F<A, Boolean> isLessThan(final A a) {
122139
* @return A function that returns true if its argument is greater than the argument to this method.
123140
*/
124141
public F<A, Boolean> isGreaterThan(final A a) {
125-
return a2 -> compare(a2, a) == Ordering.GT;
142+
return compose(o -> o != Ordering.GT, f.f(a));
126143
}
127144

128145
/**
@@ -151,19 +168,19 @@ public A min(final A a1, final A a2) {
151168
/**
152169
* A function that returns the greater of its two arguments.
153170
*/
154-
public final F<A, F<A, A>> max = curry(this::max);
171+
public final F<A, F<A, A>> max;
155172

156173
/**
157174
* A function that returns the lesser of its two arguments.
158175
*/
159-
public final F<A, F<A, A>> min = curry(this::min);
176+
public final F<A, F<A, A>> min;
160177

161178
public final Semigroup<A> minSemigroup() {
162-
return semigroup(this::min);
179+
return semigroup(min);
163180
}
164181

165182
public final Semigroup<A> maxSemigroup() {
166-
return semigroup(this::max);
183+
return semigroup(max);
167184
}
168185

169186
public final Ord<A> reverse() { return ord(Function.flip(f)); }
@@ -181,92 +198,52 @@ public static <A> Ord<A> ord(final F<A, F<A, Ordering>> f) {
181198
/**
182199
* An order instance for the <code>boolean</code> type.
183200
*/
184-
public static final Ord<Boolean> booleanOrd = ord(
185-
a1 -> a2 -> {
186-
final int x = a1.compareTo(a2);
187-
return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT;
188-
});
201+
public static final Ord<Boolean> booleanOrd = comparableOrd();
189202

190203
/**
191204
* An order instance for the <code>byte</code> type.
192205
*/
193-
public static final Ord<Byte> byteOrd = ord(
194-
a1 -> a2 -> {
195-
final int x = a1.compareTo(a2);
196-
return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT;
197-
});
206+
public static final Ord<Byte> byteOrd = comparableOrd();
198207

199208
/**
200209
* An order instance for the <code>char</code> type.
201210
*/
202-
public static final Ord<Character> charOrd = ord(
203-
a1 -> a2 -> {
204-
final int x = a1.compareTo(a2);
205-
return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT;
206-
});
211+
public static final Ord<Character> charOrd = comparableOrd();
207212

208213
/**
209214
* An order instance for the <code>double</code> type.
210215
*/
211-
public static final Ord<Double> doubleOrd = ord(
212-
a1 -> a2 -> {
213-
final int x = a1.compareTo(a2);
214-
return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT;
215-
});
216+
public static final Ord<Double> doubleOrd = comparableOrd();
216217

217218
/**
218219
* An order instance for the <code>float</code> type.
219220
*/
220-
public static final Ord<Float> floatOrd = ord(
221-
a1 -> a2 -> {
222-
final int x = a1.compareTo(a2);
223-
return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT;
224-
});
221+
public static final Ord<Float> floatOrd = comparableOrd();
225222

226223
/**
227224
* An order instance for the <code>int</code> type.
228225
*/
229-
public static final Ord<Integer> intOrd = ord(
230-
a1 -> a2 -> {
231-
final int x = a1.compareTo(a2);
232-
return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT;
233-
});
226+
public static final Ord<Integer> intOrd = comparableOrd();
234227

235228
/**
236229
* An order instance for the <code>BigInteger</code> type.
237230
*/
238-
public static final Ord<BigInteger> bigintOrd = ord(
239-
a1 -> a2 -> {
240-
final int x = a1.compareTo(a2);
241-
return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT;
242-
});
231+
public static final Ord<BigInteger> bigintOrd = comparableOrd();
243232

244233
/**
245234
* An order instance for the <code>BigDecimal</code> type.
246235
*/
247-
public static final Ord<BigDecimal> bigdecimalOrd = ord(
248-
a1 -> a2 -> {
249-
final int x = a1.compareTo(a2);
250-
return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT;
251-
});
236+
public static final Ord<BigDecimal> bigdecimalOrd = comparableOrd();
252237

253238
/**
254239
* An order instance for the <code>long</code> type.
255240
*/
256-
public static final Ord<Long> longOrd = ord(
257-
a1 -> a2 -> {
258-
final int x = a1.compareTo(a2);
259-
return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT;
260-
});
241+
public static final Ord<Long> longOrd = comparableOrd();
261242

262243
/**
263244
* An order instance for the <code>short</code> type.
264245
*/
265-
public static final Ord<Short> shortOrd = ord(
266-
a1 -> a2 -> {
267-
final int x = a1.compareTo(a2);
268-
return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT;
269-
});
246+
public static final Ord<Short> shortOrd = comparableOrd();
270247

271248
/**
272249
* An order instance for the {@link Ordering} type.
@@ -284,23 +261,17 @@ public static <A> Ord<A> ord(final F<A, F<A, Ordering>> f) {
284261
/**
285262
* An order instance for the {@link String} type.
286263
*/
287-
public static final Ord<String> stringOrd = ord(
288-
a1 -> a2 -> {
289-
final int x = a1.compareTo(a2);
290-
return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT;
291-
});
264+
public static final Ord<String> stringOrd = comparableOrd();
292265

293266
/**
294267
* An order instance for the {@link StringBuffer} type.
295268
*/
296-
public static final Ord<StringBuffer> stringBufferOrd =
297-
ord(a1 -> a2 -> stringOrd.compare(a1.toString(), a2.toString()));
269+
public static final Ord<StringBuffer> stringBufferOrd = stringOrd.contramap(StringBuffer::toString);
298270

299271
/**
300272
* An order instance for the {@link StringBuffer} type.
301273
*/
302-
public static final Ord<StringBuilder> stringBuilderOrd =
303-
ord(a1 -> a2 -> stringOrd.compare(a1.toString(), a2.toString()));
274+
public static final Ord<StringBuilder> stringBuilderOrd = stringOrd.contramap(StringBuilder::toString);
304275

305276
/**
306277
* An order instance for the {@link Option} type.
@@ -514,9 +485,9 @@ public static <A extends Comparable<A>> Ord<A> comparableOrd() {
514485
* @see #hashEqualsOrd()
515486
*/
516487
public static <A> Ord<A> hashOrd() {
517-
return ord(a -> a2 -> {
518-
final int x = a.hashCode() - a2.hashCode();
519-
return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT;
488+
return ord(a -> {
489+
int aHash = a.hashCode();
490+
return a2 -> Ordering.fromInt(Integer.compare(aHash, a2.hashCode()));
520491
});
521492
}
522493

@@ -528,9 +499,12 @@ public static <A> Ord<A> hashOrd() {
528499
* @return An order instance that is based on {@link Object#hashCode()} and {@link Object#equals}.
529500
*/
530501
public static <A> Ord<A> hashEqualsOrd() {
531-
return ord(a -> a2 -> {
532-
final int x = a.hashCode() - a2.hashCode();
533-
return x < 0 ? Ordering.LT : x == 0 && a.equals(a2) ? Ordering.EQ : Ordering.GT;
502+
return ord(a -> {
503+
int aHash = a.hashCode();
504+
return a2 -> {
505+
final int a2Hash = a2.hashCode();
506+
return aHash < a2Hash ? Ordering.LT : aHash == a2Hash && a.equals(a2) ? Ordering.EQ : Ordering.GT;
507+
};
534508
});
535509
}
536510

core/src/main/java/fj/Show.java

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package fj;
22

33
import fj.data.*;
4+
import fj.data.fingertrees.FingerTree;
5+
import fj.data.fingertrees.Node;
46
import fj.data.hlist.HList;
57
import fj.data.vector.V2;
68
import fj.data.vector.V3;
@@ -301,6 +303,44 @@ public static <A> Show<Tree<A>> treeShow(final Show<A> sa) {
301303
});
302304
}
303305

306+
public static <V, A> Show<fj.data.fingertrees.Digit<V, A>> digitShow(final Show<V> sv, final Show<A> sa) {
307+
return show(d -> {
308+
String s = d.match(
309+
o -> "One(" + o.measure() + " -> " + o.value() + ")",
310+
two -> "Two(" + two.measure() + " -> " + v2Show(sa).showS(two.values()) + ")",
311+
three -> "Three(" + three.measure() + " -> " + v3Show(sa).showS(three.values()) + ")",
312+
four -> "Four(" + four.measure() + " -> " + v4Show(sa).showS(four.values()) + ")"
313+
);
314+
return Stream.fromString(s);
315+
});
316+
}
317+
318+
public static <V, A> Show<Node<V, A>> nodeShow(final Show<V> sv, final Show<A> sa) {
319+
return show(n -> {
320+
final String s = n.match(
321+
n2 -> "Node2(" + n2.measure() + " -> " + v2Show(sa).showS(n2.toVector()) + ")",
322+
n3 -> "Node3(" + n3.measure() + " -> " + v3Show(sa).showS(n3.toVector()) + ")");
323+
return Stream.fromString(s);
324+
});
325+
}
326+
327+
public static <V, A> Show<FingerTree<V, A>> fingerTreeShow(final Show<V> sv, final Show<A> sa) {
328+
329+
return show(ft -> {
330+
String sep = ", ";
331+
String str = ft.match(e -> "Empty()",
332+
s -> "Single(" + sv.showS(ft.measure()) + " -> " + sa.showS(s.value()) + ")",
333+
d -> "Deep(" + d.measure() + " -> " +
334+
digitShow(sv, sa).showS(d.prefix()) + sep +
335+
fingerTreeShow(sv, nodeShow(sv, sa)).showS(d.middle()) + sep +
336+
digitShow(sv, sa).showS(d.suffix()) +
337+
")"
338+
);
339+
return Stream.fromString(str);
340+
});
341+
}
342+
343+
304344
public static <A> Show<Seq<A>> seqShow(final Show<A> sa) {
305345
return show(s -> streamShow(sa, "Seq(", ",", ")").show(s.toStream()));
306346
}
@@ -337,7 +377,7 @@ public static <K, V> Show<TreeMap<K, V>> treeMapShow(final Show<K> sk, final Sho
337377
* @return A show instance for the {@link P2 tuple-2} type.
338378
*/
339379
public static <A, B> Show<P2<A, B>> p2MapShow(final Show<A> sa, final Show<B> sb) {
340-
return p2Show(sa, sb, "(", ":", ")");
380+
return p2Show(sa, sb, "(", ": ", ")");
341381
}
342382

343383
/**
@@ -550,6 +590,12 @@ public static <A, B, C, D, E> Show<P5<A, B, C, D, E>> p5Show(final Show<A> sa, f
550590
.append(sg.show(p._7())).snoc(',').append(sh.show(p._8())).snoc(')'));
551591
}
552592

593+
public static <K, V> Show<PriorityQueue<K, V>> priorityQueueShow(Show<K> sk, Show<V> sv) {
594+
return show(pq -> {
595+
return streamShow(p2MapShow(sk, sv), "PriorityQueue(", ", ", ")").show(pq.toStream());
596+
});
597+
}
598+
553599
/**
554600
* A show instance for a vector-2.
555601
*

0 commit comments

Comments
 (0)