View Javadoc

1   package io.atlassian.fugue.optic;
2   
3   import io.atlassian.fugue.Either;
4   
5   import java.util.function.Function;
6   
7   /**
8    * A {@link PSetter} is a generalisation of Functor map: - `map: (A => B)
9    * => F[A] => F[B]` - `modify: (A => B) => S => T`
10   * <p>
11   * {@link PSetter} stands for Polymorphic Setter as it set and modify methods
12   * change a type `A` to `B` and `S` to `T`.
13   * <p>
14   * {@link PTraversal}, {@link POptional}, {@link PPrism}, {@link PLens} and
15   * {@link PIso} are valid {@link PSetter}
16   *
17   * @param <S> the source of a {@link PSetter}
18   * @param <T> the modified source of a {@link PSetter}
19   * @param <A> the target of a {@link PSetter}
20   * @param <B> the modified target of a {@link PSetter}
21   */
22  public abstract class PSetter<S, T, A, B> {
23  
24    PSetter() {
25      super();
26    }
27  
28    /**
29     * modify polymorphically the target of a {@link PSetter} with a function
30     */
31    public abstract Function<S, T> modify(Function<A, B> f);
32  
33    /**
34     * set polymorphically the target of a {@link PSetter} with a value
35     */
36    public abstract Function<S, T> set(final B b);
37  
38    /**
39     * join two {@link PSetter} with the same target
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    /** Compose methods between a {@link PSetter} and another Optics */
47    /*************************************************************/
48  
49    /**
50     * compose a {@link PSetter} with a {@link PSetter}
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     * compose a {@link PSetter} with a {@link PTraversal}
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     * compose a {@link PSetter} with a {@link POptional}
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     * compose a {@link PSetter} with a {@link PPrism}
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     * compose a {@link PSetter} with a {@link PLens}
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     * compose a {@link PSetter} with a {@link PIso}
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 }