Skip to content

Commit 4161ddd

Browse files
committed
Max/Min/-By semigroups
1 parent f031e22 commit 4161ddd

File tree

9 files changed

+273
-0
lines changed

9 files changed

+273
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
88
- `Fn3-8` static factory overloads to aid in coercing lambdas
99
- Adding composition guarantees to `LensLike`
1010
- `CmpEqBy`, `CmpEq`, `GTBy`, `GT`, `LTBy`, `LT`, `GTEBy`, `GTE`, `LTEBy`, and `LTE` inequality checks
11+
- `MinBy`, `MaxBy`, `Min`, and `Max` semigroups
1112

1213
## [3.0.3] - 2018-05-27
1314
### Added
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.jnape.palatable.lambda.semigroup.builtin;
2+
3+
import com.jnape.palatable.lambda.functions.Fn1;
4+
import com.jnape.palatable.lambda.semigroup.Semigroup;
5+
6+
import static com.jnape.palatable.lambda.functions.builtin.fn1.Id.id;
7+
import static com.jnape.palatable.lambda.semigroup.builtin.MaxBy.maxBy;
8+
9+
/**
10+
* A {@link Semigroup} over <code>A</code> that chooses between two values <code>x</code> and <code>y</code> via the
11+
* following rules:
12+
* <ul>
13+
* <li>If <code>x</code> is strictly less than <code>y</code>, return <code>y</code></li>
14+
* <li>Otherwise, return <code>x</code></li>
15+
* </ul>
16+
*
17+
* @param <A> the value type
18+
* @see MaxBy
19+
* @see Min
20+
*/
21+
public final class Max<A extends Comparable<A>> implements Semigroup<A> {
22+
23+
private static final Max INSTANCE = new Max();
24+
25+
private Max() {
26+
}
27+
28+
@Override
29+
public A apply(A x, A y) {
30+
return maxBy(id(), x, y);
31+
}
32+
33+
@SuppressWarnings("unchecked")
34+
public static <A extends Comparable<A>> Max<A> max() {
35+
return INSTANCE;
36+
}
37+
38+
public static <A extends Comparable<A>> Fn1<A, A> max(A x) {
39+
return Max.<A>max().apply(x);
40+
}
41+
42+
public static <A extends Comparable<A>> A max(A x, A y) {
43+
return max(x).apply(y);
44+
}
45+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.jnape.palatable.lambda.semigroup.builtin;
2+
3+
import com.jnape.palatable.lambda.functions.Fn1;
4+
import com.jnape.palatable.lambda.functions.specialized.SemigroupFactory;
5+
import com.jnape.palatable.lambda.semigroup.Semigroup;
6+
7+
import java.util.function.Function;
8+
9+
import static com.jnape.palatable.lambda.functions.builtin.fn3.LTBy.ltBy;
10+
11+
/**
12+
* Given a mapping function from some type <code>A</code> to some {@link Comparable} type <code>B</code>, produce a
13+
* {@link Semigroup} over <code>A</code> that chooses between two values <code>x</code> and <code>y</code> via the
14+
* following rules:
15+
* <ul>
16+
* <li>If <code>x</code> is strictly less than <code>y</code> in terms of <code>B</code>, return <code>y</code></li>
17+
* <li>Otherwise, return <code>x</code></li>
18+
* </ul>
19+
*
20+
* @param <A> the value type
21+
* @param <B> the mapped comparison type
22+
* @see Max
23+
* @see MinBy
24+
*/
25+
public final class MaxBy<A, B extends Comparable<B>> implements SemigroupFactory<Function<? super A, ? extends B>, A> {
26+
27+
private static final MaxBy INSTANCE = new MaxBy();
28+
29+
private MaxBy() {
30+
}
31+
32+
@Override
33+
public Semigroup<A> apply(Function<? super A, ? extends B> compareFn) {
34+
return (x, y) -> ltBy(compareFn, x, y) ? y : x;
35+
}
36+
37+
@SuppressWarnings("unchecked")
38+
public static <A, B extends Comparable<B>> MaxBy<A, B> maxBy() {
39+
return INSTANCE;
40+
}
41+
42+
public static <A, B extends Comparable<B>> Semigroup<A> maxBy(
43+
Function<? super A, ? extends B> compareFn) {
44+
return MaxBy.<A, B>maxBy().apply(compareFn);
45+
}
46+
47+
public static <A, B extends Comparable<B>> Fn1<A, A> maxBy(Function<? super A, ? extends B> compareFn, A x) {
48+
return MaxBy.<A, B>maxBy(compareFn).apply(x);
49+
}
50+
51+
public static <A, B extends Comparable<B>> A maxBy(Function<? super A, ? extends B> compareFn, A x, A y) {
52+
return maxBy(compareFn, x).apply(y);
53+
}
54+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.jnape.palatable.lambda.semigroup.builtin;
2+
3+
import com.jnape.palatable.lambda.functions.Fn1;
4+
import com.jnape.palatable.lambda.semigroup.Semigroup;
5+
6+
import static com.jnape.palatable.lambda.functions.builtin.fn1.Id.id;
7+
import static com.jnape.palatable.lambda.semigroup.builtin.MinBy.minBy;
8+
9+
/**
10+
* A {@link Semigroup} over <code>A</code> that chooses between two values <code>x</code> and <code>y</code> via the
11+
* following rules:
12+
* <ul>
13+
* <li>If <code>x</code> is strictly greater than <code>y</code>, return <code>y</code></li>
14+
* <li>Otherwise, return <code>x</code></li>
15+
* </ul>
16+
*
17+
* @param <A> the value type
18+
* @see MinBy
19+
* @see Max
20+
*/
21+
public final class Min<A extends Comparable<A>> implements Semigroup<A> {
22+
23+
private static final Min INSTANCE = new Min();
24+
25+
private Min() {
26+
}
27+
28+
@Override
29+
public A apply(A x, A y) {
30+
return minBy(id(), x, y);
31+
}
32+
33+
@SuppressWarnings("unchecked")
34+
public static <A extends Comparable<A>> Min<A> min() {
35+
return INSTANCE;
36+
}
37+
38+
public static <A extends Comparable<A>> Fn1<A, A> min(A x) {
39+
return Min.<A>min().apply(x);
40+
}
41+
42+
public static <A extends Comparable<A>> A min(A x, A y) {
43+
return min(x).apply(y);
44+
}
45+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.jnape.palatable.lambda.semigroup.builtin;
2+
3+
import com.jnape.palatable.lambda.functions.Fn1;
4+
import com.jnape.palatable.lambda.functions.specialized.SemigroupFactory;
5+
import com.jnape.palatable.lambda.semigroup.Semigroup;
6+
7+
import java.util.function.Function;
8+
9+
import static com.jnape.palatable.lambda.functions.builtin.fn3.GTBy.gtBy;
10+
11+
/**
12+
* Given a mapping function from some type <code>A</code> to some {@link Comparable} type <code>B</code>, produce a
13+
* {@link Semigroup} over <code>A</code> that chooses between two values <code>x</code> and <code>y</code> via the
14+
* following rules:
15+
* <ul>
16+
* <li>If <code>x</code> is strictly greater than <code>y</code> in terms of <code>B</code>, return <code>y</code></li>
17+
* <li>Otherwise, return <code>x</code></li>
18+
* </ul>
19+
*
20+
* @param <A> the value type
21+
* @param <B> the mapped comparison type
22+
* @see Min
23+
* @see MaxBy
24+
*/
25+
public final class MinBy<A, B extends Comparable<B>> implements SemigroupFactory<Function<? super A, ? extends B>, A> {
26+
27+
private static final MinBy INSTANCE = new MinBy();
28+
29+
private MinBy() {
30+
}
31+
32+
@Override
33+
public Semigroup<A> apply(Function<? super A, ? extends B> compareFn) {
34+
return (x, y) -> gtBy(compareFn, x, y) ? y : x;
35+
}
36+
37+
@SuppressWarnings("unchecked")
38+
public static <A, B extends Comparable<B>> MinBy<A, B> minBy() {
39+
return INSTANCE;
40+
}
41+
42+
public static <A, B extends Comparable<B>> Semigroup<A> minBy(
43+
Function<? super A, ? extends B> compareFn) {
44+
return MinBy.<A, B>minBy().apply(compareFn);
45+
}
46+
47+
public static <A, B extends Comparable<B>> Fn1<A, A> minBy(Function<? super A, ? extends B> compareFn, A x) {
48+
return MinBy.<A, B>minBy(compareFn).apply(x);
49+
}
50+
51+
public static <A, B extends Comparable<B>> A minBy(Function<? super A, ? extends B> compareFn, A x, A y) {
52+
return minBy(compareFn, x).apply(y);
53+
}
54+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.jnape.palatable.lambda.semigroup.builtin;
2+
3+
import org.junit.Test;
4+
5+
import static com.jnape.palatable.lambda.functions.builtin.fn1.Id.id;
6+
import static com.jnape.palatable.lambda.semigroup.builtin.MaxBy.maxBy;
7+
import static org.junit.Assert.assertEquals;
8+
9+
public class MaxByTest {
10+
11+
@Test
12+
public void semigroup() {
13+
assertEquals((Integer) 1, maxBy(id(), 1, 0));
14+
assertEquals((Integer) 1, maxBy(id(), 1, 1));
15+
assertEquals((Integer) 2, maxBy(id(), 1, 2));
16+
17+
assertEquals("ab", maxBy(String::length, "ab", "a"));
18+
assertEquals("ab", maxBy(String::length, "ab", "cd"));
19+
assertEquals("bc", maxBy(String::length, "a", "bc"));
20+
}
21+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.jnape.palatable.lambda.semigroup.builtin;
2+
3+
import org.junit.Test;
4+
5+
import static com.jnape.palatable.lambda.semigroup.builtin.Max.max;
6+
import static org.junit.Assert.assertEquals;
7+
8+
public class MaxTest {
9+
10+
@Test
11+
public void semigroup() {
12+
assertEquals((Integer) 1, max(1, 0));
13+
assertEquals((Integer) 1, max(1, 1));
14+
assertEquals((Integer) 2, max(1, 2));
15+
}
16+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.jnape.palatable.lambda.semigroup.builtin;
2+
3+
import org.junit.Test;
4+
5+
import static com.jnape.palatable.lambda.functions.builtin.fn1.Id.id;
6+
import static com.jnape.palatable.lambda.semigroup.builtin.MinBy.minBy;
7+
import static org.junit.Assert.assertEquals;
8+
9+
public class MinByTest {
10+
11+
@Test
12+
public void semigroup() {
13+
assertEquals((Integer) 1, minBy(id(), 1, 2));
14+
assertEquals((Integer) 1, minBy(id(), 1, 1));
15+
assertEquals((Integer) 0, minBy(id(), 1, 0));
16+
17+
assertEquals("a", minBy(String::length, "a", "ab"));
18+
assertEquals("ab", minBy(String::length, "ab", "cd"));
19+
assertEquals("c", minBy(String::length, "ab", "c"));
20+
}
21+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.jnape.palatable.lambda.semigroup.builtin;
2+
3+
import org.junit.Test;
4+
5+
import static com.jnape.palatable.lambda.semigroup.builtin.Min.min;
6+
import static org.junit.Assert.assertEquals;
7+
8+
public class MinTest {
9+
10+
@Test
11+
public void semigroup() {
12+
assertEquals((Integer) 1, min(1, 2));
13+
assertEquals((Integer) 1, min(1, 1));
14+
assertEquals((Integer) 0, min(1, 0));
15+
}
16+
}

0 commit comments

Comments
 (0)