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