1 package io.atlassian.fugue.optic;
2
3 import io.atlassian.fugue.Either;
4 import io.atlassian.fugue.Monoid;
5 import io.atlassian.fugue.Pair;
6
7 import java.util.function.BinaryOperator;
8 import java.util.function.Function;
9 import java.util.function.Supplier;
10
11
12
13
14
15
16
17
18
19
20 public abstract class Getter<S, A> {
21
22 Getter() {
23 super();
24 }
25
26
27
28
29 public abstract A get(S s);
30
31
32
33
34 public final <S1> Getter<Either<S, S1>, A> sum(final Getter<S1, A> other) {
35 return getter(e -> e.fold(this::get, other::get));
36 }
37
38
39
40
41 public final <S1, A1> Getter<Pair<S, S1>, Pair<A, A1>> product(final Getter<S1, A1> other) {
42 return getter(p2 -> Pair.pair(this.get(p2.left()), other.get(p2.right())));
43 }
44
45 public final <B> Getter<Pair<S, B>, Pair<A, B>> first() {
46 return getter(p -> Pair.pair(this.get(p.left()), p.right()));
47 }
48
49 public final <B> Getter<Pair<B, S>, Pair<B, A>> second() {
50 return getter(p -> Pair.pair(p.left(), this.get(p.right())));
51 }
52
53
54
55
56
57
58
59
60 public final <B> Fold<S, B> composeFold(final Fold<A, B> other) {
61 return asFold().composeFold(other);
62 }
63
64
65
66
67 public final <B> Getter<S, B> composeGetter(final Getter<A, B> other) {
68 return getter(s -> other.get(get(s)));
69 }
70
71
72
73
74 public final <B, C, D> Fold<S, C> composeOptional(final POptional<A, B, C, D> other) {
75 return asFold().composeOptional(other);
76 }
77
78
79
80
81 public final <B, C, D> Fold<S, C> composePrism(final PPrism<A, B, C, D> other) {
82 return asFold().composePrism(other);
83 }
84
85
86
87
88 public final <B, C, D> Getter<S, C> composeLens(final PLens<A, B, C, D> other) {
89 return composeGetter(other.asGetter());
90 }
91
92
93
94
95 public final <B, C, D> Getter<S, C> composeIso(final PIso<A, B, C, D> other) {
96 return composeGetter(other.asGetter());
97 }
98
99
100
101
102
103
104
105
106 public final Fold<S, A> asFold() {
107 return new Fold<S, A>() {
108 @Override public <B> Function<S, B> foldMap(final Monoid<B> monoid, final Function<A, B> f) {
109 return s -> f.apply(get(s));
110 }
111 };
112 }
113
114 public static <A> Getter<A, A> id() {
115 return PIso.<A, A> pId().asGetter();
116 }
117
118 public static <A> Getter<Either<A, A>, A> codiagonal() {
119 return getter(e -> e.fold(Function.identity(), Function.identity()));
120 }
121
122 public static <S, A> Getter<S, A> getter(final Function<S, A> get) {
123 return new Getter<S, A>() {
124
125 @Override public A get(final S s) {
126 return get.apply(s);
127 }
128 };
129 }
130 }