1 package io.atlassian.fugue.optic;
2
3 import io.atlassian.fugue.*;
4
5 import java.util.Collections;
6 import java.util.function.*;
7 import java.util.stream.Stream;
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 public abstract class PTraversal<S, T, A, B> {
23
24
25
26
27
28 public abstract <C> Function<S, Function<C, T>> modifyFunctionF(Function<A, Function<C, B>> f);
29
30
31
32
33
34 public abstract <L> Function<S, Either<L, T>> modifyEitherF(Function<A, Either<L, B>> f);
35
36
37
38
39
40 public abstract Function<S, Option<T>> modifyOptionF(Function<A, Option<B>> f);
41
42
43
44
45
46 public abstract Function<S, Iterable<T>> modifyIterableF(Function<A, Iterable<B>> f);
47
48
49
50
51
52 public abstract Function<S, Supplier<T>> modifySupplierF(Function<A, Supplier<B>> f);
53
54
55
56
57
58 public abstract Function<S, Pair<T, T>> modifyPairF(Function<A, Pair<B, B>> f);
59
60
61
62
63 public abstract <M> Function<S, M> foldMap(Monoid<M> monoid, Function<A, M> f);
64
65
66
67
68 public final Function<S, A> fold(final Monoid<A> monoid) {
69 return foldMap(monoid, Function.identity());
70 }
71
72
73
74
75 public final Iterable<A> getAll(final S s) {
76 return foldMap(Monoids.iterable(), Collections::singleton).apply(s);
77 }
78
79
80
81
82 public final Function<S, Option<A>> find(final Predicate<A> p) {
83 return foldMap(Monoids.firstOption(), a -> p.test(a) ? Option.some(a) : Option.none());
84 }
85
86
87
88
89 public final Option<A> headOption(final S s) {
90 return find(__ -> (Boolean.TRUE)).apply(s);
91 }
92
93
94
95
96 public final Predicate<S> exist(final Predicate<A> p) {
97 return foldMap(Monoids.disjunction, p::test)::apply;
98 }
99
100
101
102
103 public final Predicate<S> all(final Predicate<A> p) {
104 return foldMap(Monoids.conjunction, p::test)::apply;
105 }
106
107
108
109
110 public final Function<S, T> modify(final Function<A, B> f) {
111 return s -> this.modifySupplierF(a -> Suppliers.ofInstance(f.apply(a))).apply(s).get();
112 }
113
114
115
116
117 public final Function<S, T> set(final B b) {
118 return modify(__ -> (b));
119 }
120
121
122
123
124 public final <S1, T1> PTraversal<Either<S, S1>, Either<T, T1>, A, B> sum(final PTraversal<S1, T1, A, B> other) {
125 final PTraversal<S, T, A, B> self = this;
126 return new PTraversal<Either<S, S1>, Either<T, T1>, A, B>() {
127
128 @Override public <C> Function<Either<S, S1>, Function<C, Either<T, T1>>> modifyFunctionF(final Function<A, Function<C, B>> f) {
129 return ss1 -> ss1.fold(s -> self.modifyFunctionF(f).apply(s).andThen(Eithers.toLeft()),
130 s1 -> other.modifyFunctionF(f).apply(s1).andThen(Eithers.toRight()));
131 }
132
133 @Override public <L> Function<Either<S, S1>, Either<L, Either<T, T1>>> modifyEitherF(final Function<A, Either<L, B>> f) {
134 return ss1 -> ss1.fold(s -> self.modifyEitherF(f).apply(s).right().map(Eithers.toLeft()),
135 s1 -> other.modifyEitherF(f).apply(s1).right().map(Eithers.toRight()));
136 }
137
138 @Override public Function<Either<S, S1>, Option<Either<T, T1>>> modifyOptionF(final Function<A, Option<B>> f) {
139 return ss1 -> ss1.fold(s -> self.modifyOptionF(f).apply(s).map(Eithers.toLeft()),
140 s1 -> other.modifyOptionF(f).apply(s1).map(Eithers.toRight()));
141 }
142
143 @Override public Function<Either<S, S1>, Iterable<Either<T, T1>>> modifyIterableF(final Function<A, Iterable<B>> f) {
144 return ss1 -> ss1.fold(s -> Iterables.map(self.modifyIterableF(f).apply(s), Eithers.toLeft()),
145 s1 -> Iterables.map(other.modifyIterableF(f).apply(s1), Eithers.toRight()));
146 }
147
148 @Override public Function<Either<S, S1>, Supplier<Either<T, T1>>> modifySupplierF(final Function<A, Supplier<B>> f) {
149 return ss1 -> ss1.fold(s -> Suppliers.compose(Eithers.toLeft(), self.modifySupplierF(f).apply(s)),
150 s1 -> Suppliers.compose(Eithers.toRight(), other.modifySupplierF(f).apply(s1)));
151 }
152
153 @Override public Function<Either<S, S1>, Pair<Either<T, T1>, Either<T, T1>>> modifyPairF(final Function<A, Pair<B, B>> f) {
154 return ss1 -> ss1.fold(s -> Pair.map(self.modifyPairF(f).apply(s), Eithers.toLeft()),
155 s1 -> Pair.map(other.modifyPairF(f).apply(s1), Eithers.toRight()));
156 }
157
158 @Override public <M> Function<Either<S, S1>, M> foldMap(final Monoid<M> monoid, final Function<A, M> f) {
159 return ss1 -> ss1.fold(self.foldMap(monoid, f), other.foldMap(monoid, f));
160 }
161
162 };
163 }
164
165
166
167
168
169
170
171
172 public final <C> Fold<S, C> composeFold(final Fold<A, C> other) {
173 return asFold().composeFold(other);
174 }
175
176
177
178
179
180
181 public final <C> Fold<S, C> composeFold(final Getter<A, C> other) {
182 return asFold().composeGetter(other);
183 }
184
185
186
187
188 public final <C, D> PSetter<S, T, C, D> composeSetter(final PSetter<A, B, C, D> other) {
189 return asSetter().composeSetter(other);
190 }
191
192
193
194
195 public final <C, D> PTraversal<S, T, C, D> composeTraversal(final PTraversal<A, B, C, D> other) {
196 final PTraversal<S, T, A, B> self = this;
197 return new PTraversal<S, T, C, D>() {
198
199 @Override public <G> Function<S, Function<G, T>> modifyFunctionF(final Function<C, Function<G, D>> f) {
200 return self.modifyFunctionF(other.modifyFunctionF(f));
201 }
202
203 @Override public <L> Function<S, Either<L, T>> modifyEitherF(final Function<C, Either<L, D>> f) {
204 return self.modifyEitherF(other.modifyEitherF(f));
205 }
206
207 @Override public Function<S, Option<T>> modifyOptionF(final Function<C, Option<D>> f) {
208 return self.modifyOptionF(other.modifyOptionF(f));
209 }
210
211 @Override public Function<S, Iterable<T>> modifyIterableF(final Function<C, Iterable<D>> f) {
212 return self.modifyIterableF(other.modifyIterableF(f));
213 }
214
215 @Override public Function<S, Supplier<T>> modifySupplierF(final Function<C, Supplier<D>> f) {
216 return self.modifySupplierF(other.modifySupplierF(f));
217 }
218
219 @Override public Function<S, Pair<T, T>> modifyPairF(final Function<C, Pair<D, D>> f) {
220 return self.modifyPairF(other.modifyPairF(f));
221 }
222
223 @Override public <M> Function<S, M> foldMap(final Monoid<M> monoid, final Function<C, M> f) {
224 return self.foldMap(monoid, other.foldMap(monoid, f));
225 }
226 };
227 }
228
229
230
231
232 public final <C, D> PTraversal<S, T, C, D> composeOptional(final POptional<A, B, C, D> other) {
233 return composeTraversal(other.asTraversal());
234 }
235
236
237
238
239 public final <C, D> PTraversal<S, T, C, D> composePrism(final PPrism<A, B, C, D> other) {
240 return composeTraversal(other.asTraversal());
241 }
242
243
244
245
246 public final <C, D> PTraversal<S, T, C, D> composeLens(final PLens<A, B, C, D> other) {
247 return composeTraversal(other.asTraversal());
248 }
249
250
251
252
253 public final <C, D> PTraversal<S, T, C, D> composeIso(final PIso<A, B, C, D> other) {
254 return composeTraversal(other.asTraversal());
255 }
256
257
258
259
260
261
262
263
264 public final Fold<S, A> asFold() {
265 return new Fold<S, A>() {
266 @Override public <M> Function<S, M> foldMap(final Monoid<M> monoid, final Function<A, M> f) {
267 return PTraversal.this.foldMap(monoid, f);
268 }
269 };
270 }
271
272
273
274
275 public PSetter<S, T, A, B> asSetter() {
276 return PSetter.pSetter(this::modify);
277 }
278
279 public static <S, T> PTraversal<S, T, S, T> pId() {
280 return PIso.<S, T> pId().asTraversal();
281 }
282
283 public static <S, T> PTraversal<Either<S, S>, Either<T, T>, S, T> pCodiagonal() {
284 return new PTraversal<Either<S, S>, Either<T, T>, S, T>() {
285
286 @Override public <C> Function<Either<S, S>, Function<C, Either<T, T>>> modifyFunctionF(final Function<S, Function<C, T>> f) {
287 return s -> s.bimap(f, f).fold(f1 -> f1.andThen(Eithers.toLeft()), f1 -> f1.andThen(Eithers.toRight()));
288 }
289
290 @Override public <L> Function<Either<S, S>, Either<L, Either<T, T>>> modifyEitherF(final Function<S, Either<L, T>> f) {
291 return s -> s.bimap(f, f).fold(e -> e.right().map(Eithers.toLeft()), e -> e.right().map(Eithers.toRight()));
292 }
293
294 @Override public Function<Either<S, S>, Option<Either<T, T>>> modifyOptionF(final Function<S, Option<T>> f) {
295 return s -> s.bimap(f, f).fold(o -> o.map(Eithers.toLeft()), o -> o.map(Eithers.toRight()));
296 }
297
298 @Override public Function<Either<S, S>, Iterable<Either<T, T>>> modifyIterableF(final Function<S, Iterable<T>> f) {
299 return s -> s.bimap(f, f).fold(ts -> Iterables.map(ts, Eithers.toLeft()), ts -> Iterables.map(ts, Eithers.toRight()));
300 }
301
302 @Override public Function<Either<S, S>, Supplier<Either<T, T>>> modifySupplierF(final Function<S, Supplier<T>> f) {
303 return s -> s.bimap(f, f).fold(p1 -> Suppliers.compose(Eithers.toLeft(), p1), p1 -> Suppliers.compose(Eithers.toRight(), p1));
304 }
305
306 @Override public Function<Either<S, S>, Pair<Either<T, T>, Either<T, T>>> modifyPairF(final Function<S, Pair<T, T>> f) {
307 return s -> s.bimap(f, f).fold(tt -> Pair.map(tt, Eithers.toLeft()), tt -> Pair.map(tt, Eithers.toRight()));
308 }
309
310 @Override public <M> Function<Either<S, S>, M> foldMap(final Monoid<M> monoid, final Function<S, M> f) {
311 return s -> s.fold(f, f);
312 }
313 };
314 }
315
316 public static <S, T, A, B> PTraversal<S, T, A, B> pTraversal(final Function<S, A> get1, final Function<S, A> get2,
317 final BiFunction<B, B, Function<S, T>> set) {
318 return new PTraversal<S, T, A, B>() {
319
320 @Override public <C> Function<S, Function<C, T>> modifyFunctionF(final Function<A, Function<C, B>> f) {
321 return s -> Functions.ap(f.apply(get2.apply(s)), f.apply(get1.apply(s)).andThen(b1 -> b2 -> set.apply(b1, b2).apply(s)));
322 }
323
324 @Override public <L> Function<S, Either<L, T>> modifyEitherF(final Function<A, Either<L, B>> f) {
325 return s -> f.apply(get2.apply(s)).right().ap(f.apply(get1.apply(s)).right().<Function<B, T>> map(b1 -> b2 -> set.apply(b1, b2).apply(s)));
326 }
327
328 @Override public Function<S, Option<T>> modifyOptionF(final Function<A, Option<B>> f) {
329 return s -> Options.ap(f.apply(get2.apply(s)), f.apply(get1.apply(s)).<Function<B, T>> map(b1 -> b2 -> set.apply(b1, b2).apply(s)));
330 }
331
332 @Override public Function<S, Iterable<T>> modifyIterableF(final Function<A, Iterable<B>> f) {
333 return s -> Iterables.ap(f.apply(get2.apply(s)), Iterables.map(f.apply(get1.apply(s)), b1 -> b2 -> set.apply(b1, b2).apply(s)));
334 }
335
336 @Override public Function<S, Supplier<T>> modifySupplierF(final Function<A, Supplier<B>> f) {
337 return s -> Suppliers.ap(f.apply(get2.apply(s)), Suppliers.compose(b1 -> b2 -> set.apply(b1, b2).apply(s), f.apply(get1.apply(s))));
338 }
339
340 @Override public Function<S, Pair<T, T>> modifyPairF(final Function<A, Pair<B, B>> f) {
341 return s -> Pair.ap(f.apply(get2.apply(s)), Pair.map(f.apply(get1.apply(s)), b1 -> b2 -> set.apply(b1, b2).apply(s)));
342 }
343
344 @Override public <M> Function<S, M> foldMap(final Monoid<M> monoid, final Function<A, M> f) {
345 return s -> monoid.append(f.apply(get1.apply(s)), f.apply(get2.apply(s)));
346 }
347 };
348 }
349
350 public static <S, T, A, B> PTraversal<S, T, A, B> pTraversal(final Function<S, A> get1, final Function<S, A> get2, final Function<S, A> get3,
351 final Function<B, Function<B, Function<B, Function<S, T>>>> set) {
352 return fromCurried(pTraversal(get1, get2, (b1, b2) -> s -> (b3 -> set.apply(b1).apply(b2).apply(b3).apply(s))), get3);
353 }
354
355 public static <S, T, A, B> PTraversal<S, T, A, B> pTraversal(final Function<S, A> get1, final Function<S, A> get2, final Function<S, A> get3,
356 final Function<S, A> get4, final Function<B, Function<B, Function<B, Function<B, Function<S, T>>>>> set) {
357 return fromCurried(pTraversal(get1, get2, get3, b1 -> b2 -> b3 -> s -> b4 -> set.apply(b1).apply(b2).apply(b3).apply(b4).apply(s)), get4);
358 }
359
360 public static <S, T, A, B> PTraversal<S, T, A, B> pTraversal(final Function<S, A> get1, final Function<S, A> get2, final Function<S, A> get3,
361 final Function<S, A> get4, final Function<S, A> get5, final Function<B, Function<B, Function<B, Function<B, Function<B, Function<S, T>>>>>> set) {
362 return fromCurried(
363 pTraversal(get1, get2, get3, get4, b1 -> b2 -> b3 -> b4 -> s -> b5 -> set.apply(b1).apply(b2).apply(b3).apply(b4).apply(b5).apply(s)), get5);
364 }
365
366 public static <S, T, A, B> PTraversal<S, T, A, B> pTraversal(final Function<S, A> get1, final Function<S, A> get2, final Function<S, A> get3,
367 final Function<S, A> get4, final Function<S, A> get5, final Function<S, A> get6,
368 final Function<B, Function<B, Function<B, Function<B, Function<B, Function<B, Function<S, T>>>>>>> set) {
369 return fromCurried(
370 pTraversal(get1, get2, get3, get4, get5,
371 b1 -> b2 -> b3 -> b4 -> b5 -> s -> b6 -> set.apply(b1).apply(b2).apply(b3).apply(b4).apply(b5).apply(b6).apply(s)), get6);
372 }
373
374 private static <S, T, A, B> PTraversal<S, T, A, B> fromCurried(final PTraversal<S, Function<B, T>, A, B> curriedTraversal,
375 final Function<S, A> lastGet) {
376 return new PTraversal<S, T, A, B>() {
377
378 @Override public <C> Function<S, Function<C, T>> modifyFunctionF(final Function<A, Function<C, B>> f) {
379 return s -> Functions.ap(f.apply(lastGet.apply(s)), curriedTraversal.modifyFunctionF(f).apply(s));
380 }
381
382 @Override public <L> Function<S, Either<L, T>> modifyEitherF(final Function<A, Either<L, B>> f) {
383 return s -> f.apply(lastGet.apply(s)).right().ap(curriedTraversal.modifyEitherF(f).apply(s));
384 }
385
386 @Override public Function<S, Option<T>> modifyOptionF(final Function<A, Option<B>> f) {
387 return s -> Options.ap(f.apply(lastGet.apply(s)), curriedTraversal.modifyOptionF(f).apply(s));
388 }
389
390 @Override public Function<S, Iterable<T>> modifyIterableF(final Function<A, Iterable<B>> f) {
391 return s -> Iterables.ap(f.apply(lastGet.apply(s)), curriedTraversal.modifyIterableF(f).apply(s));
392 }
393
394 @Override public Function<S, Supplier<T>> modifySupplierF(final Function<A, Supplier<B>> f) {
395 return s -> Suppliers.ap(f.apply(lastGet.apply(s)), curriedTraversal.modifySupplierF(f).apply(s));
396 }
397
398 @Override public Function<S, Pair<T, T>> modifyPairF(final Function<A, Pair<B, B>> f) {
399 return s -> Pair.ap(f.apply(lastGet.apply(s)), curriedTraversal.modifyPairF(f).apply(s));
400 }
401
402 @Override public <M> Function<S, M> foldMap(final Monoid<M> monoid, final Function<A, M> f) {
403 return s -> monoid.append(curriedTraversal.foldMap(monoid, f).apply(s), f.apply(lastGet.apply(s)));
404 }
405 };
406 }
407 }