Skip to content

Commit f3e89cd

Browse files
committed
Adding First and Last, Optional monoids that choose the first or last present value, respectively
1 parent c5c5f29 commit f3e89cd

5 files changed

Lines changed: 144 additions & 0 deletions

File tree

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
- `ChoiceN` types, representing concrete coproduct implementations that are also `Functor` and `BiFunctor`
99
- `toMap`, `last`, `cons`, `prependAll`, `intersperse`
1010
- `Tuple2/3/4#into`, for applying the values in a tuple as positional arguments to a function.
11+
- `First` and `Last` monoids over `Optional`
1112

1213
### Changed
1314
- `CoProductN.[a-e]()` static factory methods moved to equivalent `ChoiceN` class. Coproduct interfaces now solely represent methods, no longer have anonymous implementations, and no longer require a `Functor` constraint
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.jnape.palatable.lambda.monoid.builtin;
2+
3+
import com.jnape.palatable.lambda.functions.Fn1;
4+
import com.jnape.palatable.lambda.monoid.Monoid;
5+
6+
import java.util.Optional;
7+
8+
/**
9+
* A {@link Monoid} instance formed by <code>{@link Optional}&lt;A&gt;</code>. The application to two {@link Optional}
10+
* values produces the first non-empty value, or <code>Optional.empty()</code> if all values are empty.
11+
*
12+
* @param <A> the Optional value parameter type
13+
* @see Last
14+
* @see Present
15+
* @see Monoid
16+
* @see Optional
17+
*/
18+
public final class First<A> implements Monoid<Optional<A>> {
19+
20+
private static final First INSTANCE = new First();
21+
22+
private First() {
23+
}
24+
25+
@Override
26+
public Optional<A> identity() {
27+
return Optional.empty();
28+
}
29+
30+
@Override
31+
public Optional<A> apply(Optional<A> x, Optional<A> y) {
32+
return x.map(Optional::of).orElse(y);
33+
}
34+
35+
@SuppressWarnings("unchecked")
36+
public static <A> First<A> first() {
37+
return INSTANCE;
38+
}
39+
40+
public static <A> Fn1<Optional<A>, Optional<A>> first(Optional<A> x) {
41+
return First.<A>first().apply(x);
42+
}
43+
44+
public static <A> Optional<A> first(Optional<A> x, Optional<A> y) {
45+
return first(x).apply(y);
46+
}
47+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.jnape.palatable.lambda.monoid.builtin;
2+
3+
import com.jnape.palatable.lambda.functions.Fn1;
4+
import com.jnape.palatable.lambda.monoid.Monoid;
5+
6+
import java.util.Optional;
7+
8+
/**
9+
* A {@link Monoid} instance formed by <code>{@link Optional}&lt;A&gt;</code>. The application to two {@link Optional}
10+
* values produces the last non-empty value, or <code>Optional.empty()</code> if all values are empty.
11+
*
12+
* @param <A> the Optional value parameter type
13+
* @see First
14+
* @see Present
15+
* @see Monoid
16+
* @see Optional
17+
*/
18+
public final class Last<A> implements Monoid<Optional<A>> {
19+
private static final Last INSTANCE = new Last();
20+
21+
private Last() {
22+
}
23+
24+
@Override
25+
public Optional<A> identity() {
26+
return Optional.empty();
27+
}
28+
29+
@Override
30+
public Optional<A> apply(Optional<A> x, Optional<A> y) {
31+
return y.map(Optional::of).orElse(x);
32+
}
33+
34+
@SuppressWarnings("unchecked")
35+
public static <A> Last<A> last() {
36+
return INSTANCE;
37+
}
38+
39+
public static <A> Fn1<Optional<A>, Optional<A>> last(Optional<A> x) {
40+
return Last.<A>last().apply(x);
41+
}
42+
43+
public static <A> Optional<A> last(Optional<A> x, Optional<A> y) {
44+
return last(x).apply(y);
45+
}
46+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.jnape.palatable.lambda.monoid.builtin;
2+
3+
import org.junit.Test;
4+
5+
import java.util.Optional;
6+
7+
import static com.jnape.palatable.lambda.monoid.builtin.First.first;
8+
import static org.junit.Assert.assertEquals;
9+
10+
public class FirstTest {
11+
12+
@Test
13+
public void identity() {
14+
assertEquals(Optional.empty(), first().identity());
15+
}
16+
17+
@Test
18+
public void monoid() {
19+
First<Integer> first = first();
20+
assertEquals(Optional.of(1), first.apply(Optional.of(1), Optional.of(2)));
21+
assertEquals(Optional.of(1), first.apply(Optional.of(1), Optional.empty()));
22+
assertEquals(Optional.of(2), first.apply(Optional.empty(), Optional.of(2)));
23+
assertEquals(Optional.empty(), first.apply(Optional.empty(), Optional.empty()));
24+
}
25+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.jnape.palatable.lambda.monoid.builtin;
2+
3+
import org.junit.Test;
4+
5+
import java.util.Optional;
6+
7+
import static com.jnape.palatable.lambda.monoid.builtin.Last.last;
8+
import static org.junit.Assert.assertEquals;
9+
10+
public class LastTest {
11+
12+
@Test
13+
public void identity() {
14+
assertEquals(Optional.empty(), last().identity());
15+
}
16+
17+
@Test
18+
public void monoid() {
19+
Last<Integer> last = last();
20+
assertEquals(Optional.of(2), last.apply(Optional.of(1), Optional.of(2)));
21+
assertEquals(Optional.of(2), last.apply(Optional.empty(), Optional.of(2)));
22+
assertEquals(Optional.of(1), last.apply(Optional.of(1), Optional.empty()));
23+
assertEquals(Optional.empty(), last.apply(Optional.empty(), Optional.empty()));
24+
}
25+
}

0 commit comments

Comments
 (0)