Skip to content

Commit bf28fb1

Browse files
committed
Splitting out coproducts interfaces from choice ADTs
1 parent 749d16c commit bf28fb1

File tree

18 files changed

+1451
-1028
lines changed

18 files changed

+1451
-1028
lines changed

src/main/java/com/jnape/palatable/lambda/adt/Either.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import com.jnape.palatable.lambda.adt.coproduct.CoProduct2;
44
import com.jnape.palatable.lambda.functions.specialized.checked.CheckedFn1;
55
import com.jnape.palatable.lambda.functions.specialized.checked.CheckedSupplier;
6+
import com.jnape.palatable.lambda.functor.Bifunctor;
7+
import com.jnape.palatable.lambda.functor.Functor;
68

79
import java.util.Objects;
810
import java.util.Optional;
@@ -23,7 +25,7 @@
2325
* @param <L> The left parameter type
2426
* @param <R> The right parameter type
2527
*/
26-
public abstract class Either<L, R> implements CoProduct2<L, R> {
28+
public abstract class Either<L, R> implements CoProduct2<L, R>, Functor<R>, Bifunctor<L, R> {
2729

2830
private Either() {
2931
}
@@ -146,8 +148,8 @@ public final Either<R, L> invert() {
146148
public final Either<L, R> merge(BiFunction<? super L, ? super L, ? extends L> leftFn,
147149
BiFunction<? super R, ? super R, ? extends R> rightFn,
148150
Either<L, R>... others) {
149-
return foldLeft((x, y) -> x.match(l1 -> y.<Either<L, R>>match(l2 -> left(leftFn.apply(l1, l2)), r -> left(l1)),
150-
r1 -> y.<Either<L, R>>match(Either::left, r2 -> right(rightFn.apply(r1, r2)))),
151+
return foldLeft((x, y) -> x.match(l1 -> y.match(l2 -> left(leftFn.apply(l1, l2)), r -> left(l1)),
152+
r1 -> y.match(Either::left, r2 -> right(rightFn.apply(r1, r2)))),
151153
this,
152154
asList(others));
153155
}
@@ -200,13 +202,13 @@ public final <R2> Either<L, R2> fmap(Function<? super R, ? extends R2> fn) {
200202
@Override
201203
@SuppressWarnings("unchecked")
202204
public final <L2> Either<L2, R> biMapL(Function<? super L, ? extends L2> fn) {
203-
return (Either<L2, R>) CoProduct2.super.biMapL(fn);
205+
return (Either<L2, R>) Bifunctor.super.biMapL(fn);
204206
}
205207

206208
@Override
207209
@SuppressWarnings("unchecked")
208210
public final <R2> Either<L, R2> biMapR(Function<? super R, ? extends R2> fn) {
209-
return (Either<L, R2>) CoProduct2.super.biMapR(fn);
211+
return (Either<L, R2>) Bifunctor.super.biMapR(fn);
210212
}
211213

212214
@Override
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package com.jnape.palatable.lambda.adt.choice;
2+
3+
import com.jnape.palatable.lambda.adt.Either;
4+
import com.jnape.palatable.lambda.adt.coproduct.CoProduct2;
5+
import com.jnape.palatable.lambda.functor.Bifunctor;
6+
import com.jnape.palatable.lambda.functor.Functor;
7+
8+
import java.util.Objects;
9+
import java.util.function.Function;
10+
11+
/**
12+
* Canonical ADT representation of {@link CoProduct2} that is also a {@link Functor} and {@link Bifunctor}. Unlike
13+
* {@link Either}, there is no concept of "success" or "failure", so the domain of reasonable function semantics is
14+
* more limited.
15+
*
16+
* @param <A> a type parameter representing the first possible type of this choice
17+
* @param <B> a type parameter representing the second possible type of this choice
18+
* @see Either
19+
* @see Choice3
20+
*/
21+
public abstract class Choice2<A, B> implements CoProduct2<A, B>, Functor<B>, Bifunctor<A, B> {
22+
23+
private Choice2() {
24+
}
25+
26+
@Override
27+
public final <C> Choice3<A, B, C> diverge() {
28+
return match(Choice3::a, Choice3::b);
29+
}
30+
31+
@Override
32+
public final <C> Choice2<A, C> fmap(Function<? super B, ? extends C> fn) {
33+
return biMapR(fn);
34+
}
35+
36+
@Override
37+
@SuppressWarnings("unchecked")
38+
public final <C> Choice2<C, B> biMapL(Function<? super A, ? extends C> fn) {
39+
return (Choice2<C, B>) Bifunctor.super.biMapL(fn);
40+
}
41+
42+
@Override
43+
@SuppressWarnings("unchecked")
44+
public final <C> Choice2<A, C> biMapR(Function<? super B, ? extends C> fn) {
45+
return (Choice2<A, C>) Bifunctor.super.biMapR(fn);
46+
}
47+
48+
@Override
49+
public final <C, D> Choice2<C, D> biMap(Function<? super A, ? extends C> lFn,
50+
Function<? super B, ? extends D> rFn) {
51+
return match(a -> a(lFn.apply(a)), b -> b(rFn.apply(b)));
52+
}
53+
54+
/**
55+
* Static factory method for wrapping a value of type <code>A</code> in a {@link Choice2}.
56+
*
57+
* @param a the value
58+
* @param <A> a type parameter representing the first possible type of this choice
59+
* @param <B> a type parameter representing the second possible type of this choice
60+
* @return the wrapped value as a Choice2&lt;A, B&gt;
61+
*/
62+
public static <A, B> Choice2<A, B> a(A a) {
63+
return new _A<>(a);
64+
}
65+
66+
/**
67+
* Static factory method for wrapping a value of type <code>B</code> in a {@link Choice2}.
68+
*
69+
* @param b the value
70+
* @param <A> a type parameter representing the first possible type of this choice
71+
* @param <B> a type parameter representing the second possible type of this choice
72+
* @return the wrapped value as a Choice2&lt;A, B&gt;
73+
*/
74+
public static <A, B> Choice2<A, B> b(B b) {
75+
return new _B<>(b);
76+
}
77+
78+
private static final class _A<A, B> extends Choice2<A, B> {
79+
80+
private final A a;
81+
82+
private _A(A a) {
83+
this.a = a;
84+
}
85+
86+
@Override
87+
public <R> R match(Function<? super A, ? extends R> aFn, Function<? super B, ? extends R> bFn) {
88+
return aFn.apply(a);
89+
}
90+
91+
@Override
92+
public boolean equals(Object other) {
93+
return other instanceof _A
94+
&& Objects.equals(a, ((_A) other).a);
95+
}
96+
97+
@Override
98+
public int hashCode() {
99+
return Objects.hash(a);
100+
}
101+
102+
@Override
103+
public String toString() {
104+
return "Choice2{" +
105+
"a=" + a +
106+
'}';
107+
}
108+
}
109+
110+
private static final class _B<A, B> extends Choice2<A, B> {
111+
112+
private final B b;
113+
114+
private _B(B b) {
115+
this.b = b;
116+
}
117+
118+
@Override
119+
public <R> R match(Function<? super A, ? extends R> aFn, Function<? super B, ? extends R> bFn) {
120+
return bFn.apply(b);
121+
}
122+
123+
@Override
124+
public boolean equals(Object other) {
125+
return other instanceof _B
126+
&& Objects.equals(b, ((_B) other).b);
127+
}
128+
129+
@Override
130+
public int hashCode() {
131+
return Objects.hash(b);
132+
}
133+
134+
@Override
135+
public String toString() {
136+
return "Choice2{" +
137+
"b=" + b +
138+
'}';
139+
}
140+
}
141+
}
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
package com.jnape.palatable.lambda.adt.choice;
2+
3+
import com.jnape.palatable.lambda.adt.coproduct.CoProduct2;
4+
import com.jnape.palatable.lambda.adt.coproduct.CoProduct3;
5+
import com.jnape.palatable.lambda.functor.Bifunctor;
6+
import com.jnape.palatable.lambda.functor.Functor;
7+
8+
import java.util.Objects;
9+
import java.util.function.Function;
10+
11+
/**
12+
* Canonical ADT representation of {@link CoProduct3} that is also a {@link Functor} and {@link Bifunctor}.
13+
*
14+
* @param <A> a type parameter representing the first possible type of this choice
15+
* @param <B> a type parameter representing the second possible type of this choice
16+
* @param <C> a type parameter representing the third possible type of this choice
17+
* @see Choice2
18+
* @see Choice4
19+
*/
20+
public abstract class Choice3<A, B, C> implements CoProduct3<A, B, C>, Functor<C>, Bifunctor<B, C> {
21+
22+
private Choice3() {
23+
}
24+
25+
@Override
26+
public final <D> Choice4<A, B, C, D> diverge() {
27+
return match(Choice4::a, Choice4::b, Choice4::c);
28+
}
29+
30+
@Override
31+
public final Choice2<A, B> converge(Function<? super C, ? extends CoProduct2<A, B>> convergenceFn) {
32+
return match(Choice2::a, Choice2::b, convergenceFn.andThen(cp2 -> cp2.match(Choice2::a, Choice2::b)));
33+
}
34+
35+
@Override
36+
public final <D> Choice3<A, B, D> fmap(Function<? super C, ? extends D> fn) {
37+
return biMapR(fn);
38+
}
39+
40+
@Override
41+
@SuppressWarnings("unchecked")
42+
public final <D> Choice3<A, D, C> biMapL(Function<? super B, ? extends D> fn) {
43+
return (Choice3<A, D, C>) Bifunctor.super.biMapL(fn);
44+
}
45+
46+
@Override
47+
@SuppressWarnings("unchecked")
48+
public final <D> Choice3<A, B, D> biMapR(Function<? super C, ? extends D> fn) {
49+
return (Choice3<A, B, D>) Bifunctor.super.biMapR(fn);
50+
}
51+
52+
@Override
53+
public final <D, E> Choice3<A, D, E> biMap(Function<? super B, ? extends D> lFn,
54+
Function<? super C, ? extends E> rFn) {
55+
return match(Choice3::a, b -> b(lFn.apply(b)), c -> c(rFn.apply(c)));
56+
}
57+
58+
/**
59+
* Static factory method for wrapping a value of type <code>A</code> in a {@link Choice3}.
60+
*
61+
* @param a the value
62+
* @param <A> a type parameter representing the first possible type of this choice
63+
* @param <B> a type parameter representing the second possible type of this choice
64+
* @param <C> a type parameter representing the third possible type of this choice
65+
* @return the wrapped value as a Choice3&lt;A, B, C&gt;
66+
*/
67+
public static <A, B, C> Choice3<A, B, C> a(A a) {
68+
return new _A<>(a);
69+
}
70+
71+
/**
72+
* Static factory method for wrapping a value of type <code>A</code> in a {@link Choice3}.
73+
*
74+
* @param b the value
75+
* @param <A> a type parameter representing the first possible type of this choice
76+
* @param <B> a type parameter representing the second possible type of this choice
77+
* @param <C> a type parameter representing the third possible type of this choice
78+
* @return the wrapped value as a Choice3&lt;A, B, C&gt;
79+
*/
80+
public static <A, B, C> Choice3<A, B, C> b(B b) {
81+
return new _B<>(b);
82+
}
83+
84+
/**
85+
* Static factory method for wrapping a value of type <code>A</code> in a {@link Choice3}.
86+
*
87+
* @param c the value
88+
* @param <A> a type parameter representing the first possible type of this choice
89+
* @param <B> a type parameter representing the second possible type of this choice
90+
* @param <C> a type parameter representing the third possible type of this choice
91+
* @return the wrapped value as a Choice3&lt;A, B, C&gt;
92+
*/
93+
public static <A, B, C> Choice3<A, B, C> c(C c) {
94+
return new _C<>(c);
95+
}
96+
97+
private static final class _A<A, B, C> extends Choice3<A, B, C> {
98+
99+
private final A a;
100+
101+
private _A(A a) {
102+
this.a = a;
103+
}
104+
105+
@Override
106+
public <R> R match(Function<? super A, ? extends R> aFn, Function<? super B, ? extends R> bFn,
107+
Function<? super C, ? extends R> cFn) {
108+
return aFn.apply(a);
109+
}
110+
111+
@Override
112+
public boolean equals(Object other) {
113+
return other instanceof _A
114+
&& Objects.equals(a, ((_A) other).a);
115+
}
116+
117+
@Override
118+
public int hashCode() {
119+
return Objects.hash(a);
120+
}
121+
122+
@Override
123+
public String toString() {
124+
return "Choice3{" +
125+
"a=" + a +
126+
'}';
127+
}
128+
}
129+
130+
private static final class _B<A, B, C> extends Choice3<A, B, C> {
131+
132+
private final B b;
133+
134+
private _B(B b) {
135+
this.b = b;
136+
}
137+
138+
@Override
139+
public <R> R match(Function<? super A, ? extends R> aFn, Function<? super B, ? extends R> bFn,
140+
Function<? super C, ? extends R> cFn) {
141+
return bFn.apply(b);
142+
}
143+
144+
@Override
145+
public boolean equals(Object other) {
146+
return other instanceof _B
147+
&& Objects.equals(b, ((_B) other).b);
148+
}
149+
150+
@Override
151+
public int hashCode() {
152+
return Objects.hash(b);
153+
}
154+
155+
@Override
156+
public String toString() {
157+
return "Choice3{" +
158+
"b=" + b +
159+
'}';
160+
}
161+
}
162+
163+
private static final class _C<A, B, C> extends Choice3<A, B, C> {
164+
165+
private final C c;
166+
167+
private _C(C c) {
168+
this.c = c;
169+
}
170+
171+
@Override
172+
public <R> R match(Function<? super A, ? extends R> aFn, Function<? super B, ? extends R> bFn,
173+
Function<? super C, ? extends R> cFn) {
174+
return cFn.apply(c);
175+
}
176+
177+
@Override
178+
public boolean equals(Object other) {
179+
return other instanceof _C
180+
&& Objects.equals(c, ((_C) other).c);
181+
}
182+
183+
@Override
184+
public int hashCode() {
185+
return Objects.hash(c);
186+
}
187+
188+
@Override
189+
public String toString() {
190+
return "Choice3{" +
191+
"c=" + c +
192+
'}';
193+
}
194+
}
195+
196+
197+
}

0 commit comments

Comments
 (0)