View Javadoc
1   package io.atlassian.fugue.optic.law;
2   
3   import io.atlassian.fugue.Either;
4   import io.atlassian.fugue.Eithers;
5   import io.atlassian.fugue.Option;
6   import io.atlassian.fugue.Options;
7   import io.atlassian.fugue.Pair;
8   import io.atlassian.fugue.Suppliers;
9   import io.atlassian.fugue.law.IsEq;
10  import io.atlassian.fugue.optic.PLens;
11  
12  import java.util.Collections;
13  import java.util.List;
14  import java.util.function.Function;
15  
16  import static io.atlassian.fugue.law.IsEq.isEq;
17  import static java.util.Spliterator.ORDERED;
18  import static java.util.Spliterators.spliteratorUnknownSize;
19  import static java.util.stream.Collectors.toList;
20  import static java.util.stream.StreamSupport.stream;
21  
22  public final class LensLaws<S, A> {
23  
24    private final PLens<S, S, A, A> lens;
25  
26    public LensLaws(PLens<S, S, A, A> lens) {
27      this.lens = lens;
28    }
29  
30    /**
31     * set what you get
32     */
33    public IsEq<S> getSet(S s) {
34      return isEq(lens.set(lens.get(s)).apply(s), s);
35    }
36  
37    /**
38     * get what you set
39     */
40    public IsEq<A> setGet(S s, A a) {
41      return isEq(lens.get(lens.set(a).apply(s)), a);
42    }
43  
44    /**
45     * set idempotent
46     */
47    public IsEq<S> setIdempotent(S s, A a) {
48      return isEq(lens.set(a).apply(lens.set(a).apply(s)), lens.set(a).apply(s));
49    }
50  
51    /**
52     * modify id = id
53     */
54    public IsEq<S> modifyIdentity(S s) {
55      return isEq(lens.modify(Function.<A> identity()).apply(s), s);
56    }
57  
58    /**
59     * modifyF Applicative.point(_) = Applicative.point(_)
60     */
61    public IsEq<S> modifySupplierFPoint(S s) {
62      return isEq(lens.modifySupplierF(Suppliers::ofInstance).apply(s).get(), s);
63    }
64  
65    /**
66     * modifyF Applicative.point(_) = Applicative.point(_)
67     */
68    public IsEq<Either<String, S>> modifyEitherFPoint(S s) {
69      return isEq(lens.<String> modifyEitherF(Eithers.toRight()).apply(s), Either.right(s));
70    }
71  
72    /**
73     * modifyF Applicative.point(_) = Applicative.point(_)
74     */
75    public IsEq<Option<S>> modifyOptionFPoint(S s) {
76      return isEq(lens.modifyOptionF(Options.toOption()).apply(s), Option.some(s));
77    }
78  
79    /**
80     * modifyF Applicative.point(_) = Applicative.point(_)
81     */
82    public IsEq<Pair<S, S>> modifyPairFPoint(S s) {
83      return isEq(lens.modifyPairF(a -> Pair.pair(a, a)).apply(s), Pair.pair(s, s));
84    }
85  
86    /**
87     * modifyF Applicative.point(_) = Applicative.point(_)
88     */
89    public IsEq<S> modifyFunctionFPoint(S s) {
90      return isEq(lens.<String> modifyFunctionF(a -> __ -> a).apply(s).apply(""), s);
91    }
92  
93    /**
94     * modifyF Applicative.point(_) = Applicative.point(_)
95     */
96    public IsEq<List<S>> modifyIterableFPoint(S s) {
97      return isEq(stream(spliteratorUnknownSize(lens.modifyIterableF(Collections::singleton).apply(s).iterator(), ORDERED), false).collect(toList()),
98        Collections.singletonList(s));
99    }
100 }