View Javadoc

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