77import com .jnape .palatable .lambda .adt .hlist .Tuple2 ;
88import com .jnape .palatable .lambda .functions .Fn1 ;
99import com .jnape .palatable .lambda .functions .specialized .Pure ;
10+ import com .jnape .palatable .lambda .functor .Applicative ;
1011import com .jnape .palatable .lambda .functor .Cocartesian ;
1112import com .jnape .palatable .lambda .functor .Functor ;
1213import com .jnape .palatable .lambda .functor .Profunctor ;
1314import com .jnape .palatable .lambda .functor .builtin .Identity ;
15+ import com .jnape .palatable .lambda .functor .builtin .Lazy ;
1416import com .jnape .palatable .lambda .functor .builtin .Market ;
17+ import com .jnape .palatable .lambda .monad .Monad ;
1518import com .jnape .palatable .lambda .optics .functions .Matching ;
1619import com .jnape .palatable .lambda .optics .functions .Pre ;
1720import com .jnape .palatable .lambda .optics .functions .Re ;
1821import com .jnape .palatable .lambda .optics .functions .View ;
1922
23+ import static com .jnape .palatable .lambda .adt .Either .left ;
24+ import static com .jnape .palatable .lambda .functions .builtin .fn1 .Constantly .constantly ;
25+ import static com .jnape .palatable .lambda .functions .builtin .fn1 .Downcast .downcast ;
26+ import static com .jnape .palatable .lambda .functions .builtin .fn1 .Upcast .upcast ;
27+ import static com .jnape .palatable .lambda .optics .Prism .Simple .adapt ;
28+ import static com .jnape .palatable .lambda .optics .functions .Matching .matching ;
29+ import static com .jnape .palatable .lambda .optics .functions .Re .re ;
30+
2031/**
2132 * Prisms are {@link Iso Isos} that can fail in one direction. Example:
2233 * <pre>
4253 * @param <B> the input that guarantees its output
4354 */
4455@ FunctionalInterface
45- public interface Prism <S , T , A , B > extends
46- ProtoOptic <Cocartesian <?, ?, ?>, S , T , A , B >,
47- Optic <Cocartesian <?, ?, ?>, Identity <?>, S , T , A , B > {
56+ public interface Prism <S , T , A , B > extends ProtoOptic <Cocartesian <?, ?, ?>, S , T , A , B >, Monad <T , Prism <S , ?, A , B >> {
4857
58+ /**
59+ * Recover the two mappings encapsulated by this {@link Prism} by sending it through a {@link Market}.
60+ *
61+ * @return a {@link Tuple2 tuple} of the two mappings encapsulated by this {@link Prism}
62+ */
63+ default Tuple2 <Fn1 <? super B , ? extends T >, Fn1 <? super S , ? extends Either <T , A >>> unPrism () {
64+ return Tuple2 .fill (this .<Market <A , B , ?, ?>, Identity <?>, Identity <B >, Identity <T >,
65+ Market <A , B , A , Identity <B >>, Market <A , B , S , Identity <T >>>apply (
66+ new Market <>(Identity ::new , Either ::right )).fmap (Identity ::runIdentity ))
67+ .biMap (Market ::bt , Market ::sta );
68+ }
69+
70+ /**
71+ * {@inheritDoc}
72+ */
4973 @ Override
5074 default <CoP extends Profunctor <?, ?, ? extends Cocartesian <?, ?, ?>>,
5175 CoF extends Functor <?, ? extends Identity <?>>,
@@ -58,15 +82,62 @@ public interface Prism<S, T, A, B> extends
5882 }
5983
6084 /**
61- * Recover the two mappings encapsulated by this {@link Prism} by sending it through a {@link Market}.
62- *
63- * @return a {@link Tuple2 tuple} of the two mappings encapsulated by this {@link Prism}
85+ * {@inheritDoc}
6486 */
65- default Tuple2 <Fn1 <? super B , ? extends T >, Fn1 <? super S , ? extends Either <T , A >>> unPrism () {
66- return Tuple2 .fill (this .<Market <A , B , ?, ?>, Identity <?>, Identity <B >, Identity <T >,
67- Market <A , B , A , Identity <B >>, Market <A , B , S , Identity <T >>>apply (
68- new Market <>(Identity ::new , Either ::right )).fmap (Identity ::runIdentity ))
69- .biMap (Market ::bt , Market ::sta );
87+ @ Override
88+ default <U > Prism <S , U , A , B > pure (U u ) {
89+ return prism (constantly (left (u )), constantly (u ));
90+ }
91+
92+ /**
93+ * {@inheritDoc}
94+ */
95+ @ Override
96+ default <U > Prism <S , U , A , B > flatMap (Fn1 <? super T , ? extends Monad <U , Prism <S , ?, A , B >>> f ) {
97+ return unPrism ().into ((bt , seta ) -> prism (
98+ s -> seta .apply (s ).match (t -> matching (f .apply (t ).<Prism <S , U , A , B >>coerce (), s ), Either ::right ),
99+ b -> View .<B , B , U , U >view (re (f .apply (bt .apply (b )).coerce ())).apply (b )));
100+ }
101+
102+ /**
103+ * {@inheritDoc}
104+ */
105+ @ Override
106+ default <U > Prism <S , U , A , B > fmap (Fn1 <? super T , ? extends U > fn ) {
107+ return Monad .super .<U >fmap (fn ).coerce ();
108+ }
109+
110+ /**
111+ * {@inheritDoc}
112+ */
113+ @ Override
114+ default <U > Prism <S , U , A , B > zip (Applicative <Fn1 <? super T , ? extends U >, Prism <S , ?, A , B >> appFn ) {
115+ return Monad .super .zip (appFn ).coerce ();
116+ }
117+
118+ /**
119+ * {@inheritDoc}
120+ */
121+ @ Override
122+ default <U > Lazy <Prism <S , U , A , B >> lazyZip (
123+ Lazy <? extends Applicative <Fn1 <? super T , ? extends U >, Prism <S , ?, A , B >>> lazyAppFn ) {
124+ return Monad .super .lazyZip (lazyAppFn ).fmap (Monad <U , Prism <S , ?, A , B >>::coerce );
125+ }
126+
127+ /**
128+ * {@inheritDoc}
129+ */
130+ @ Override
131+ default <U > Prism <S , U , A , B > discardL (Applicative <U , Prism <S , ?, A , B >> appB ) {
132+ return Monad .super .discardL (appB ).coerce ();
133+ }
134+
135+ /**
136+ * {@inheritDoc}
137+ */
138+ @ Override
139+ default <U > Prism <S , T , A , B > discardR (Applicative <U , Prism <S , ?, A , B >> appB ) {
140+ return Monad .super .discardR (appB ).coerce ();
70141 }
71142
72143 /**
@@ -85,8 +156,7 @@ static <S, T, A, B> Prism<S, T, A, B> prism(Fn1<? super S, ? extends CoProduct2<
85156 Fn1 <? super B , ? extends T > bt ) {
86157 return new Prism <S , T , A , B >() {
87158 @ Override
88- public <F extends Functor <?, ? extends F >> Optic <Cocartesian <?, ?, ?>, F , S , T , A , B > toOptic (
89- Pure <? extends F > pure ) {
159+ public <F extends Applicative <?, F >> Optic <Cocartesian <?, ?, ?>, F , S , T , A , B > toOptic (Pure <F > pure ) {
90160 return Optic .<Cocartesian <?, ?, ?>,
91161 F ,
92162 S , T , A , B ,
@@ -113,8 +183,7 @@ static <S, T, A, B> Prism<S, T, A, B> prism(Fn1<? super S, ? extends CoProduct2<
113183 static <S , T , A , B > Prism <S , T , A , B > prism (ProtoOptic <? super Cocartesian <?, ?, ?>, S , T , A , B > protoOptic ) {
114184 return new Prism <S , T , A , B >() {
115185 @ Override
116- public <F extends Functor <?, ? extends F >> Optic <Cocartesian <?, ?, ?>, F , S , T , A , B > toOptic (
117- Pure <? extends F > pure ) {
186+ public <F extends Applicative <?, F >> Optic <Cocartesian <?, ?, ?>, F , S , T , A , B > toOptic (Pure <F > pure ) {
118187 Optic <? super Cocartesian <?, ?, ?>, F , S , T , A , B > optic = protoOptic .toOptic (pure );
119188 return Optic .reframe (optic );
120189 }
@@ -138,8 +207,7 @@ static <S, T, A, B> Prism<S, T, A, B> prism(
138207 Optic <? super Cocartesian <?, ?, ?>, ? super Functor <?, ?>, S , T , A , B > optic ) {
139208 return new Prism <S , T , A , B >() {
140209 @ Override
141- public <F extends Functor <?, ? extends F >> Optic <Cocartesian <?, ?, ?>, F , S , T , A , B > toOptic (
142- Pure <? extends F > pure ) {
210+ public <F extends Applicative <?, F >> Optic <Cocartesian <?, ?, ?>, F , S , T , A , B > toOptic (Pure <F > pure ) {
143211 return Optic .reframe (optic );
144212 }
145213 };
@@ -160,6 +228,12 @@ static <S, A> Prism.Simple<S, A> simplePrism(Fn1<? super S, ? extends Maybe<A>>
160228 return Prism .<S , S , A , A >prism (s -> sMaybeA .apply (s ).toEither (() -> s ), as )::toOptic ;
161229 }
162230
231+
232+ static <S , A > Prism .Simple <S , A > fromPartial (Fn1 <? super S , ? extends A > partialSa ,
233+ Fn1 <? super A , ? extends S > as ) {
234+ return adapt (prism (partialSa .<S , A >diMap (downcast (), upcast ()).choose (), as ));
235+ }
236+
163237 /**
164238 * A convenience type with a simplified type signature for common {@link Prism prism} with unified <code>S/T</code>
165239 * and <code>A/B</code> types.
0 commit comments