View Javadoc

1   package io.atlassian.fugue.optic;
2   
3   import io.atlassian.fugue.*;
4   
5   import java.util.function.BinaryOperator;
6   import java.util.function.Function;
7   import java.util.function.Supplier;
8   import java.util.stream.Stream;
9   
10  /**
11   * A {@link PLens} can be seen as a pair of functions: - `get: S => A` i.e.
12   * from an `S`, we can extract an `A` - `set: (B, S) => T` i.e. if we replace
13   * an `A` by a `B` in an `S`, we obtain a `T`
14   * <p>
15   * A {@link PLens} could also be defined as a weaker {@link PIso} where set
16   * requires an additional parameter than reverseGet.
17   * <p>
18   * {@link PLens} stands for Polymorphic Lens as it set and modify methods change
19   * a type `A` to `B` and `S` to `T`. {@link Lens} is a {@link PLens} restricted
20   * to monomorphic updates.
21   * <p>
22   * A {@link PLens} is also a valid {@link Getter}, {@link Fold},
23   * {@link POptional}, {@link PTraversal} and {@link PSetter}
24   * <p>
25   * Typically a {@link PLens} or {@link Lens} can be defined between a Product
26   * (e.g. case class, tuple, HList) and one of it is component.
27   *
28   * @param <S> the source of a {@link PLens}
29   * @param <T> the modified source of a {@link PLens}
30   * @param <A> the target of a {@link PLens}
31   * @param <B> the modified target of a {@link PLens}
32   */
33  public abstract class PLens<S, T, A, B> {
34  
35    PLens() {
36      super();
37    }
38  
39    /**
40     * get the target of a {@link PLens}
41     */
42    public abstract A get(S s);
43  
44    /**
45     * set polymorphically the target of a {@link PLens} using a function
46     */
47    public abstract Function<S, T> set(B b);
48  
49    /**
50     * modify polymorphically the target of a {@link PLens} with an Applicative
51     * function
52     */
53    public abstract <C> Function<S, Function<C, T>> modifyFunctionF(Function<A, Function<C, B>> f);
54  
55    /**
56     * modify polymorphically the target of a {@link PLens} with an Applicative
57     * function
58     */
59    public abstract <L> Function<S, Either<L, T>> modifyEitherF(Function<A, Either<L, B>> f);
60  
61    /**
62     * modify polymorphically the target of a {@link PLens} with an Applicative
63     * function
64     */
65    public abstract Function<S, Option<T>> modifyOptionF(Function<A, Option<B>> f);
66  
67    /**
68     * modify polymorphically the target of a {@link PLens} with an Applicative
69     * function
70     */
71    public abstract Function<S, Iterable<T>> modifyIterableF(final Function<A, Iterable<B>> f);
72  
73    /**
74     * modify polymorphically the target of a {@link PLens} with an Applicative
75     * function
76     */
77    public abstract Function<S, Supplier<T>> modifySupplierF(Function<A, Supplier<B>> f);
78  
79    /**
80     * modify polymorphically the target of a {@link PLens} with an Applicative
81     * function
82     */
83    public abstract Function<S, Pair<T, T>> modifyPairF(final Function<A, Pair<B, B>> f);
84  
85    /**
86     * modify polymorphically the target of a {@link PLens} using a function
87     */
88    public abstract Function<S, T> modify(final Function<A, B> f);
89  
90    /**
91     * join two {@link PLens} with the same target
92     */
93    public final <S1, T1> PLens<Either<S, S1>, Either<T, T1>, A, B> sum(final PLens<S1, T1, A, B> other) {
94      return pLens(e -> e.fold(this::get, other::get), b -> e -> e.bimap(PLens.this.set(b), other.set(b)));
95    }
96  
97    /***********************************************************/
98    /** Compose methods between a {@link PLens} and another Optics */
99    /***********************************************************/
100 
101   /**
102    * compose a {@link PLens} with a {@link Fold}
103    */
104   public final <C> Fold<S, C> composeFold(final Fold<A, C> other) {
105     return asFold().composeFold(other);
106   }
107 
108   /**
109    * compose a {@link PLens} with a {@link Getter}
110    */
111   public final <C> Getter<S, C> composeGetter(final Getter<A, C> other) {
112     return asGetter().composeGetter(other);
113   }
114 
115   /**
116    * compose a {@link PLens} with a {@link PSetter}
117    */
118   public final <C, D> PSetter<S, T, C, D> composeSetter(final PSetter<A, B, C, D> other) {
119     return asSetter().composeSetter(other);
120   }
121 
122   /**
123    * compose a {@link PLens} with a {@link PTraversal}
124    */
125   public final <C, D> PTraversal<S, T, C, D> composeTraversal(final PTraversal<A, B, C, D> other) {
126     return asTraversal().composeTraversal(other);
127   }
128 
129   /**
130    * compose a {@link PLens} with an {@link POptional}
131    */
132   public final <C, D> POptional<S, T, C, D> composeOptional(final POptional<A, B, C, D> other) {
133     return asOptional().composeOptional(other);
134   }
135 
136   /**
137    * compose a {@link PLens} with a {@link PPrism}
138    */
139   public final <C, D> POptional<S, T, C, D> composePrism(final PPrism<A, B, C, D> other) {
140     return asOptional().composeOptional(other.asOptional());
141   }
142 
143   /**
144    * compose a {@link PLens} with a {@link PLens}
145    */
146   public final <C, D> PLens<S, T, C, D> composeLens(final PLens<A, B, C, D> other) {
147     final PLens<S, T, A, B> self = this;
148     return new PLens<S, T, C, D>() {
149       @Override public C get(final S s) {
150         return other.get(self.get(s));
151       }
152 
153       @Override public Function<S, T> set(final D d) {
154         return self.modify(other.set(d));
155       }
156 
157       @Override public <G> Function<S, Function<G, T>> modifyFunctionF(final Function<C, Function<G, D>> f) {
158         return self.modifyFunctionF(other.modifyFunctionF(f));
159       }
160 
161       @Override public <L> Function<S, Either<L, T>> modifyEitherF(final Function<C, Either<L, D>> f) {
162         return self.modifyEitherF(other.modifyEitherF(f));
163       }
164 
165       @Override public Function<S, Option<T>> modifyOptionF(final Function<C, Option<D>> f) {
166         return self.modifyOptionF(other.modifyOptionF(f));
167       }
168 
169       @Override public Function<S, Iterable<T>> modifyIterableF(final Function<C, Iterable<D>> f) {
170         return self.modifyIterableF(other.modifyIterableF(f));
171       }
172 
173       @Override public Function<S, Supplier<T>> modifySupplierF(final Function<C, Supplier<D>> f) {
174         return self.modifySupplierF(other.modifySupplierF(f));
175       }
176 
177       @Override public Function<S, Pair<T, T>> modifyPairF(final Function<C, Pair<D, D>> f) {
178         return self.modifyPairF(other.modifyPairF(f));
179       }
180 
181       @Override public Function<S, T> modify(final Function<C, D> f) {
182         return self.modify(other.modify(f));
183       }
184     };
185   }
186 
187   /**
188    * compose a {@link PLens} with an {@link PIso}
189    */
190   public final <C, D> PLens<S, T, C, D> composeIso(final PIso<A, B, C, D> other) {
191     return composeLens(other.asLens());
192   }
193 
194   /************************************************************************************************/
195   /** Transformation methods to view a {@link PLens} as another Optics */
196   /************************************************************************************************/
197 
198   /**
199    * view a {@link PLens} as a {@link Fold}
200    */
201   public final Fold<S, A> asFold() {
202     return new Fold<S, A>() {
203       @Override public <M> Function<S, M> foldMap(final Monoid<M> monoid, final Function<A, M> f) {
204         return s -> f.apply(get(s));
205       }
206     };
207   }
208 
209   /**
210    * view a {@link PLens} as a {@link Getter}
211    */
212   public final Getter<S, A> asGetter() {
213     return new Getter<S, A>() {
214       @Override public A get(final S s) {
215         return PLens.this.get(s);
216       }
217     };
218   }
219 
220   /**
221    * view a {@link PLens} as a {@link PSetter}
222    */
223   public PSetter<S, T, A, B> asSetter() {
224     return new PSetter<S, T, A, B>() {
225       @Override public Function<S, T> modify(final Function<A, B> f) {
226         return PLens.this.modify(f);
227       }
228 
229       @Override public Function<S, T> set(final B b) {
230         return PLens.this.set(b);
231       }
232     };
233   }
234 
235   /**
236    * view a {@link PLens} as a {@link PTraversal}
237    */
238   public PTraversal<S, T, A, B> asTraversal() {
239     final PLens<S, T, A, B> self = this;
240     return new PTraversal<S, T, A, B>() {
241 
242       @Override public <C> Function<S, Function<C, T>> modifyFunctionF(final Function<A, Function<C, B>> f) {
243         return self.modifyFunctionF(f);
244       }
245 
246       @Override public <L> Function<S, Either<L, T>> modifyEitherF(final Function<A, Either<L, B>> f) {
247         return self.modifyEitherF(f);
248       }
249 
250       @Override public Function<S, Option<T>> modifyOptionF(final Function<A, Option<B>> f) {
251         return self.modifyOptionF(f);
252       }
253 
254       @Override public Function<S, Iterable<T>> modifyIterableF(final Function<A, Iterable<B>> f) {
255         return self.modifyIterableF(f);
256       }
257 
258       @Override public Function<S, Supplier<T>> modifySupplierF(final Function<A, Supplier<B>> f) {
259         return self.modifySupplierF(f);
260       }
261 
262       @Override public Function<S, Pair<T, T>> modifyPairF(final Function<A, Pair<B, B>> f) {
263         return self.modifyPairF(f);
264       }
265 
266       @Override public <M> Function<S, M> foldMap(final Monoid<M> monoid, final Function<A, M> f) {
267         return s -> f.apply(get(s));
268       }
269 
270     };
271   }
272 
273   /**
274    * view a {@link PLens} as an {@link POptional}
275    */
276   public POptional<S, T, A, B> asOptional() {
277     final PLens<S, T, A, B> self = this;
278     return new POptional<S, T, A, B>() {
279       @Override public Either<T, A> getOrModify(final S s) {
280         return Either.right(self.get(s));
281       }
282 
283       @Override public Function<S, T> set(final B b) {
284         return self.set(b);
285       }
286 
287       @Override public Option<A> getOption(final S s) {
288         return Option.some(self.get(s));
289       }
290 
291       @Override public <C> Function<S, Function<C, T>> modifyFunctionF(final Function<A, Function<C, B>> f) {
292         return self.modifyFunctionF(f);
293       }
294 
295       @Override public <L> Function<S, Either<L, T>> modifyEitherF(final Function<A, Either<L, B>> f) {
296         return self.modifyEitherF(f);
297       }
298 
299       @Override public Function<S, Option<T>> modifyOptionF(final Function<A, Option<B>> f) {
300         return self.modifyOptionF(f);
301       }
302 
303       @Override public Function<S, Iterable<T>> modifyIterableF(final Function<A, Iterable<B>> f) {
304         return self.modifyIterableF(f);
305       }
306 
307       @Override public Function<S, Supplier<T>> modifySupplierF(final Function<A, Supplier<B>> f) {
308         return self.modifySupplierF(f);
309       }
310 
311       @Override public Function<S, Pair<T, T>> modifyPairF(final Function<A, Pair<B, B>> f) {
312         return self.modifyPairF(f);
313       }
314 
315       @Override public Function<S, T> modify(final Function<A, B> f) {
316         return self.modify(f);
317       }
318     };
319   }
320 
321   public static <S, T> PLens<S, T, S, T> pId() {
322     return PIso.<S, T> pId().asLens();
323   }
324 
325   /**
326    * create a {@link PLens} using a pair of functions: one to get the target,
327    * one to set the target.
328    */
329   public static <S, T, A, B> PLens<S, T, A, B> pLens(final Function<S, A> get, final Function<B, Function<S, T>> set) {
330     return new PLens<S, T, A, B>() {
331 
332       @Override public A get(final S s) {
333         return get.apply(s);
334       }
335 
336       @Override public Function<S, T> set(final B b) {
337         return set.apply(b);
338       }
339 
340       @Override public <C> Function<S, Function<C, T>> modifyFunctionF(final Function<A, Function<C, B>> f) {
341         return s -> f.apply(get.apply(s)).andThen(b -> set.apply(b).apply(s));
342       }
343 
344       @Override public <L> Function<S, Either<L, T>> modifyEitherF(final Function<A, Either<L, B>> f) {
345         return s -> f.apply(get.apply(s)).right().map(a -> set.apply(a).apply(s));
346       }
347 
348       @Override public Function<S, Option<T>> modifyOptionF(final Function<A, Option<B>> f) {
349         return s -> f.apply(get.apply(s)).map(a -> set.apply(a).apply(s));
350       }
351 
352       @Override public Function<S, Iterable<T>> modifyIterableF(final Function<A, Iterable<B>> f) {
353         return s -> Iterables.map(f.apply(get.apply(s)), a -> set.apply(a).apply(s));
354       }
355 
356       @Override public Function<S, Supplier<T>> modifySupplierF(final Function<A, Supplier<B>> f) {
357         return s -> Suppliers.compose(a -> set.apply(a).apply(s), f.apply(get.apply(s)));
358       }
359 
360       @Override public Function<S, Pair<T, T>> modifyPairF(final Function<A, Pair<B, B>> f) {
361         return s -> Pair.map(f.apply(get.apply(s)), a -> set.apply(a).apply(s));
362       }
363 
364       @Override public Function<S, T> modify(final Function<A, B> f) {
365         return s -> set.apply(f.apply(get.apply(s))).apply(s);
366       }
367 
368     };
369   }
370 }