1 package io.atlassian.fugue.optic;
2
3 import io.atlassian.fugue.Either;
4
5 import java.util.function.Function;
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 public abstract class PSetter<S, T, A, B> {
23
24 PSetter() {
25 super();
26 }
27
28
29
30
31 public abstract Function<S, T> modify(Function<A, B> f);
32
33
34
35
36 public abstract Function<S, T> set(final B b);
37
38
39
40
41 public final <S1, T1> PSetter<Either<S, S1>, Either<T, T1>, A, B> sum(final PSetter<S1, T1, A, B> other) {
42 return pSetter(f -> e -> e.bimap(modify(f), other.modify(f)));
43 }
44
45
46
47
48
49
50
51
52 public final <C, D> PSetter<S, T, C, D> composeSetter(final PSetter<A, B, C, D> other) {
53 final PSetter<S, T, A, B> self = this;
54 return new PSetter<S, T, C, D>() {
55
56 @Override public Function<S, T> modify(final Function<C, D> f) {
57 return self.modify(other.modify(f));
58 }
59
60 @Override public Function<S, T> set(final D d) {
61 return self.modify(other.set(d));
62 }
63 };
64 }
65
66
67
68
69 public final <C, D> PSetter<S, T, C, D> composeTraversal(final PTraversal<A, B, C, D> other) {
70 return composeSetter(other.asSetter());
71 }
72
73
74
75
76 public final <C, D> PSetter<S, T, C, D> composeOptional(final POptional<A, B, C, D> other) {
77 return composeSetter(other.asSetter());
78 }
79
80
81
82
83 public final <C, D> PSetter<S, T, C, D> composePrism(final PPrism<A, B, C, D> other) {
84 return composeSetter(other.asSetter());
85 }
86
87
88
89
90 public final <C, D> PSetter<S, T, C, D> composeLens(final PLens<A, B, C, D> other) {
91 return composeSetter(other.asSetter());
92 }
93
94
95
96
97 public final <C, D> PSetter<S, T, C, D> composeIso(final PIso<A, B, C, D> other) {
98 return composeSetter(other.asSetter());
99 }
100
101 public static <S, T> PSetter<S, T, S, T> pId() {
102 return PIso.<S, T> pId().asSetter();
103 }
104
105 public static <S, T> PSetter<Either<S, S>, Either<T, T>, S, T> pCodiagonal() {
106 return pSetter(f -> e -> e.bimap(f, f));
107 }
108
109 public static <S, T, A, B> PSetter<S, T, A, B> pSetter(final Function<Function<A, B>, Function<S, T>> modify) {
110 return new PSetter<S, T, A, B>() {
111 @Override public Function<S, T> modify(final Function<A, B> f) {
112 return modify.apply(f);
113 }
114
115 @Override public Function<S, T> set(final B b) {
116 return modify.apply(__ -> (b));
117 }
118 };
119 }
120 }