fp_library/types/optics/reverse.rs
1//! The `Reverse` profunctor, for reversing optic constraints.
2//!
3//! `Reverse<'a, InnerP, OuterP, S, T, A, B>` wraps a function `InnerP::Of<'a, B, A> -> InnerP::Of<'a, T, S>`.
4//! It "reverses" the profunctor structure of `InnerP`:
5//!
6//! - `InnerP: Profunctor` -> `ReverseBrand<InnerP, OuterP, S, T>: Profunctor`
7//! - `InnerP: Choice` -> `ReverseBrand<InnerP, OuterP, S, T>: Cochoice`
8//! - `InnerP: Cochoice` -> `ReverseBrand<InnerP, OuterP, S, T>: Choice`
9//! - `InnerP: Strong` -> `ReverseBrand<InnerP, OuterP, S, T>: Costrong`
10//! - `InnerP: Costrong` -> `ReverseBrand<InnerP, OuterP, S, T>: Strong`
11//!
12//! This is a port of PureScript's [`Data.Lens.Internal.Re`](https://pursuit.purescript.org/packages/purescript-profunctor-lenses/docs/Data.Lens.Internal.Re).
13
14#[fp_macros::document_module]
15mod inner {
16 use {
17 crate::{
18 Apply,
19 brands::{
20 FnBrand,
21 optics::*,
22 },
23 classes::{
24 Monoid,
25 optics::{
26 FoldOptic,
27 GetterOptic,
28 IsoOptic,
29 LensOptic,
30 PrismOptic,
31 ReviewOptic,
32 },
33 profunctor::{
34 Choice,
35 Cochoice,
36 Costrong,
37 Profunctor,
38 Strong,
39 },
40 *,
41 },
42 impl_kind,
43 kinds::*,
44 },
45 fp_macros::*,
46 std::marker::PhantomData,
47 };
48
49 /// The `Reverse` profunctor.
50 ///
51 /// Wraps a function `InnerP::Of<'a, B, A> -> InnerP::Of<'a, T, S>`, reversing
52 /// the role of the inner profunctor's type arguments.
53 ///
54 /// Corresponds to PureScript's `newtype Re p s t a b = Re (p b a -> p t s)`.
55 #[document_type_parameters(
56 "The lifetime of the functions.",
57 "The inner profunctor brand whose instances are reversed.",
58 "The outer cloneable function pointer brand for wrapping the `run` function.",
59 "The fixed source type (outer structure, contravariant).",
60 "The fixed target type (outer structure, covariant).",
61 "The varying input type (contravariant position).",
62 "The varying output type (covariant position)."
63 )]
64 pub struct Reverse<
65 'a,
66 InnerP: Profunctor,
67 PointerBrand: ToDynCloneFn,
68 S: 'a,
69 T: 'a,
70 A: 'a,
71 B: 'a,
72 > {
73 /// The wrapped function `InnerP::Of<B, A> -> InnerP::Of<T, S>`.
74 pub run: <FnBrand<PointerBrand> as CloneFn>::Of<
75 'a,
76 Apply!(<InnerP as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, B, A>),
77 Apply!(<InnerP as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, T, S>),
78 >,
79 }
80
81 #[document_type_parameters(
82 "The lifetime of the functions.",
83 "The inner profunctor brand.",
84 "The outer cloneable function pointer brand.",
85 "The fixed source type.",
86 "The fixed target type.",
87 "The varying input type.",
88 "The varying output type."
89 )]
90 impl<'a, InnerP: Profunctor, PointerBrand: ToDynCloneFn, S: 'a, T: 'a, A: 'a, B: 'a>
91 Reverse<'a, InnerP, PointerBrand, S, T, A, B>
92 {
93 /// Creates a new `Reverse` instance by wrapping a function.
94 #[document_signature]
95 ///
96 #[document_parameters("The function `InnerP::Of<B, A> -> InnerP::Of<T, S>` to wrap.")]
97 ///
98 #[document_returns("A new instance of the type.")]
99 ///
100 #[document_examples]
101 ///
102 /// ```
103 /// use fp_library::{
104 /// brands::{
105 /// RcBrand,
106 /// RcFnBrand,
107 /// optics::*,
108 /// },
109 /// types::optics::{
110 /// Reverse,
111 /// Tagged,
112 /// },
113 /// };
114 ///
115 /// // Reverse wraps a function from `Tagged<B, A>` to `Tagged<T, S>`.
116 /// let rev =
117 /// Reverse::<TaggedBrand, RcBrand, i32, i32, i32, i32>::new(|tagged: Tagged<i32, i32>| {
118 /// Tagged::new(tagged.0 + 1)
119 /// });
120 /// assert_eq!((rev.run)(Tagged::new(41)).0, 42);
121 /// ```
122 pub fn new(
123 f: impl 'a
124 + Fn(
125 Apply!(<InnerP as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, B, A>),
126 ) -> Apply!(<InnerP as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, T, S>)
127 ) -> Self {
128 Reverse {
129 run: <FnBrand<PointerBrand> as LiftFn>::new(f),
130 }
131 }
132 }
133
134 #[document_type_parameters(
135 "The lifetime of the functions.",
136 "The inner profunctor brand.",
137 "The outer cloneable function pointer brand.",
138 "The fixed source type.",
139 "The fixed target type.",
140 "The varying input type.",
141 "The varying output type."
142 )]
143 #[document_parameters("The `Reverse` instance.")]
144 impl<'a, InnerP: Profunctor, PointerBrand: ToDynCloneFn, S: 'a, T: 'a, A: 'a, B: 'a> Clone
145 for Reverse<'a, InnerP, PointerBrand, S, T, A, B>
146 {
147 #[document_signature]
148 #[document_returns("A new `Reverse` instance that is a copy of the original.")]
149 #[document_examples]
150 ///
151 /// ```
152 /// use fp_library::{
153 /// brands::{
154 /// RcBrand,
155 /// RcFnBrand,
156 /// optics::*,
157 /// },
158 /// types::optics::{
159 /// Reverse,
160 /// Tagged,
161 /// },
162 /// };
163 ///
164 /// let rev = Reverse::<TaggedBrand, RcBrand, i32, i32, i32, i32>::new(|t: Tagged<i32, i32>| {
165 /// Tagged::new(t.0)
166 /// });
167 /// let cloned = rev.clone();
168 /// assert_eq!((cloned.run)(Tagged::new(42)).0, 42);
169 /// ```
170 fn clone(&self) -> Self {
171 Reverse {
172 run: self.run.clone(),
173 }
174 }
175 }
176
177 impl_kind! {
178 impl<
179 InnerP: Profunctor + 'static,
180 PointerBrand: ToDynCloneFn + 'static,
181 S: 'static,
182 T: 'static,
183 > for ReverseBrand<InnerP, PointerBrand, S, T> {
184 #[document_default]
185 type Of<'a, A: 'a, B: 'a>: 'a = Reverse<'a, InnerP, PointerBrand, S, T, A, B>;
186 }
187 }
188
189 /// `Profunctor` instance for `ReverseBrand<InnerP, OuterP, S, T>` whenever `InnerP: Profunctor`.
190 ///
191 /// Corresponds to:
192 /// ```purescript
193 /// instance profunctorRe :: Profunctor p => Profunctor (Re p s t) where
194 /// dimap f g (Re r) = Re (r <<< dimap g f)
195 /// ```
196 #[document_type_parameters(
197 "The inner profunctor brand.",
198 "The outer cloneable function pointer brand.",
199 "The fixed source type.",
200 "The fixed target type."
201 )]
202 impl<InnerP: Profunctor + 'static, PointerBrand: ToDynCloneFn + 'static, S: 'static, T: 'static>
203 Profunctor for ReverseBrand<InnerP, PointerBrand, S, T>
204 {
205 /// Maps over both arguments of `Reverse`, swapping the roles of `f` and `g` on the inner profunctor.
206 #[document_signature]
207 #[document_type_parameters(
208 "The lifetime of the functions.",
209 "The new contravariant type.",
210 "The original contravariant type.",
211 "The original covariant type.",
212 "The new covariant type."
213 )]
214 ///
215 #[document_parameters(
216 "The contravariant function `A -> B`.",
217 "The covariant function `C -> D`.",
218 "The `Reverse` instance to transform."
219 )]
220 #[document_returns("A transformed `Reverse` instance.")]
221 ///
222 #[document_examples]
223 ///
224 /// ```
225 /// use fp_library::{
226 /// brands::{
227 /// RcBrand,
228 /// RcFnBrand,
229 /// optics::*,
230 /// },
231 /// classes::profunctor::Profunctor,
232 /// types::optics::{
233 /// Reverse,
234 /// Tagged,
235 /// },
236 /// };
237 ///
238 /// // rev.run: Tagged<i32, i32> -> Tagged<i32, i32>
239 /// let rev =
240 /// Reverse::<TaggedBrand, RcBrand, i32, i32, i32, i32>::new(|tagged: Tagged<i32, i32>| {
241 /// Tagged::new(tagged.0)
242 /// });
243 /// // dimap(ab=|x| x*2, cd=|x| x+1, rev).run(Tagged(5))
244 /// // = rev.run(TaggedBrand::dimap(cd, ab, Tagged(5)))
245 /// // = rev.run(Tagged(ab(5))) = rev.run(Tagged(10)) = Tagged(10)
246 /// let transformed = <ReverseBrand<TaggedBrand, RcBrand, i32, i32> as Profunctor>::dimap(
247 /// |x: i32| x * 2,
248 /// |x: i32| x + 1,
249 /// rev,
250 /// );
251 /// assert_eq!((transformed.run)(Tagged::new(5)).0, 10);
252 /// ```
253 fn dimap<'a, A: 'a, B: 'a, C: 'a, D: 'a>(
254 ab: impl Fn(A) -> B + 'a,
255 cd: impl Fn(C) -> D + 'a,
256 pbc: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, B, C>),
257 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A, D>) {
258 let r = pbc.run;
259 let ab = <FnBrand<PointerBrand> as LiftFn>::new(ab);
260 let cd = <FnBrand<PointerBrand> as LiftFn>::new(cd);
261 Reverse::new(move |pda| {
262 let ab = ab.clone();
263 let cd = cd.clone();
264 (*r)(InnerP::dimap(move |c| (*cd)(c), move |a| (*ab)(a), pda))
265 })
266 }
267 }
268
269 /// `Cochoice` instance for `ReverseBrand<InnerP, OuterP, S, T>` whenever `InnerP: Choice`.
270 ///
271 /// Corresponds to:
272 /// ```purescript
273 /// instance choiceRe :: Choice p => Cochoice (Re p s t) where
274 /// unleft (Re r) = Re (r <<< left)
275 /// unright (Re r) = Re (r <<< right)
276 /// ```
277 #[document_type_parameters(
278 "The inner `Choice` profunctor brand.",
279 "The outer cloneable function pointer brand.",
280 "The fixed source type.",
281 "The fixed target type."
282 )]
283 impl<InnerP: Choice + 'static, PointerBrand: ToDynCloneFn + 'static, S: 'static, T: 'static>
284 Cochoice for ReverseBrand<InnerP, PointerBrand, S, T>
285 {
286 /// Extracts from a `Reverse` that operates on `Result` types using `InnerP::left`.
287 #[document_signature]
288 ///
289 #[document_type_parameters(
290 "The lifetime of the functions.",
291 "The input type of the resulting `Reverse`.",
292 "The output type of the resulting `Reverse`.",
293 "The type of the `Ok` variant (threaded through)."
294 )]
295 ///
296 #[document_parameters("The `Reverse` instance operating on `Result` types.")]
297 ///
298 #[document_returns("A `Reverse` instance operating on the unwrapped types.")]
299 ///
300 #[document_examples]
301 ///
302 /// ```
303 /// use fp_library::{
304 /// brands::{
305 /// RcBrand,
306 /// RcFnBrand,
307 /// optics::*,
308 /// },
309 /// classes::profunctor::Cochoice,
310 /// types::optics::{
311 /// Reverse,
312 /// Tagged,
313 /// },
314 /// };
315 ///
316 /// // rev.run: Tagged<Result<String, i32>, Result<String, i32>> -> Tagged<i32, i32>
317 /// let rev =
318 /// Reverse::<TaggedBrand, RcBrand, i32, i32, Result<String, i32>, Result<String, i32>>::new(
319 /// |t: Tagged<Result<String, i32>, Result<String, i32>>| Tagged::new(t.0.unwrap_err() + 1),
320 /// );
321 /// // unleft(rev).run(Tagged(41)) = rev.run(TaggedBrand::left(Tagged(41)))
322 /// // = rev.run(Tagged(Err(41))) = Tagged(42)
323 /// let result =
324 /// <ReverseBrand<TaggedBrand, RcBrand, i32, i32> as Cochoice>::unleft::<i32, i32, String>(rev);
325 /// assert_eq!((result.run)(Tagged::new(41)).0, 42);
326 /// ```
327 fn unleft<'a, A: 'a, B: 'a, C: 'a>(
328 pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, Result<C, A>, Result<C, B>>)
329 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A, B>) {
330 let r = pab.run;
331 Reverse::new(move |pba| (*r)(InnerP::left(pba)))
332 }
333
334 /// Extracts from a `Reverse` that operates on `Result` types using `InnerP::right`.
335 #[document_signature]
336 ///
337 #[document_type_parameters(
338 "The lifetime of the functions.",
339 "The input type of the resulting `Reverse`.",
340 "The output type of the resulting `Reverse`.",
341 "The type of the `Err` variant (threaded through)."
342 )]
343 ///
344 #[document_parameters("The `Reverse` instance operating on `Result` types.")]
345 ///
346 #[document_returns("A `Reverse` instance operating on the unwrapped types.")]
347 ///
348 #[document_examples]
349 ///
350 /// ```
351 /// use fp_library::{
352 /// brands::{
353 /// RcBrand,
354 /// RcFnBrand,
355 /// optics::*,
356 /// },
357 /// classes::profunctor::Cochoice,
358 /// types::optics::{
359 /// Reverse,
360 /// Tagged,
361 /// },
362 /// };
363 ///
364 /// // rev.run: Tagged<Result<i32, String>, Result<i32, String>> -> Tagged<i32, i32>
365 /// let rev =
366 /// Reverse::<TaggedBrand, RcBrand, i32, i32, Result<i32, String>, Result<i32, String>>::new(
367 /// |t: Tagged<Result<i32, String>, Result<i32, String>>| Tagged::new(t.0.unwrap() + 1),
368 /// );
369 /// // unright(rev).run(Tagged(41)) = rev.run(TaggedBrand::right(Tagged(41)))
370 /// // = rev.run(Tagged(Ok(41))) = Tagged(42)
371 /// let result =
372 /// <ReverseBrand<TaggedBrand, RcBrand, i32, i32> as Cochoice>::unright::<i32, i32, String>(
373 /// rev,
374 /// );
375 /// assert_eq!((result.run)(Tagged::new(41)).0, 42);
376 /// ```
377 fn unright<'a, A: 'a, B: 'a, C: 'a>(
378 pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, Result<A, C>, Result<B, C>>)
379 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A, B>) {
380 let r = pab.run;
381 Reverse::new(move |pba| (*r)(InnerP::right(pba)))
382 }
383 }
384
385 /// `Choice` instance for `ReverseBrand<InnerP, OuterP, S, T>` whenever `InnerP: Cochoice`.
386 ///
387 /// Corresponds to:
388 /// ```purescript
389 /// instance cochoiceRe :: Cochoice p => Choice (Re p s t) where
390 /// left (Re r) = Re (r <<< unleft)
391 /// right (Re r) = Re (r <<< unright)
392 /// ```
393 #[document_type_parameters(
394 "The inner `Cochoice` profunctor brand.",
395 "The outer cloneable function pointer brand.",
396 "The fixed source type.",
397 "The fixed target type."
398 )]
399 impl<InnerP: Cochoice + 'static, PointerBrand: ToDynCloneFn + 'static, S: 'static, T: 'static>
400 Choice for ReverseBrand<InnerP, PointerBrand, S, T>
401 {
402 /// Lifts `Reverse` to operate on the `Err` variant of a `Result` using `InnerP::unleft`.
403 #[document_signature]
404 ///
405 #[document_type_parameters(
406 "The lifetime of the functions.",
407 "The input type of the profunctor.",
408 "The output type of the profunctor.",
409 "The type of the `Ok` variant (threaded through)."
410 )]
411 ///
412 #[document_parameters("The `Reverse` instance to lift.")]
413 ///
414 #[document_returns("A `Reverse` instance operating on `Result` types.")]
415 ///
416 #[document_examples]
417 ///
418 /// ```
419 /// use fp_library::{
420 /// brands::{
421 /// RcBrand,
422 /// optics::*,
423 /// },
424 /// classes::profunctor::Choice,
425 /// types::optics::{
426 /// Forget,
427 /// Reverse,
428 /// },
429 /// };
430 ///
431 /// // rev wraps a getter transformer: (i32 -> i32) -> (i32 -> i32)
432 /// let rev = Reverse::<ForgetBrand<RcBrand, i32>, RcBrand, i32, i32, i32, i32>::new(
433 /// |f: Forget<'_, RcBrand, i32, i32, i32>| Forget::new(move |x: i32| f.run(x) + 1),
434 /// );
435 /// // left(rev).run(getter) = rev.run(unleft(getter))
436 /// // unleft wraps input in Err: unleft(|r| r.unwrap_err()) = identity
437 /// // rev.run(identity) = |x| x + 1
438 /// let result = <ReverseBrand<ForgetBrand<RcBrand, i32>, RcBrand, i32, i32> as Choice>::left::<
439 /// i32,
440 /// i32,
441 /// String,
442 /// >(rev);
443 /// let transformed = (result.run)(Forget::new(|r: Result<String, i32>| r.unwrap_err()));
444 /// assert_eq!(transformed.run(41), 42);
445 /// ```
446 fn left<'a, A: 'a, B: 'a, C: 'a>(
447 pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A, B>)
448 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, Result<C, A>, Result<C, B>>)
449 {
450 let r = pab.run;
451 Reverse::new(move |p| (*r)(InnerP::unleft(p)))
452 }
453
454 /// Lifts `Reverse` to operate on the `Ok` variant of a `Result` using `InnerP::unright`.
455 #[document_signature]
456 ///
457 #[document_type_parameters(
458 "The lifetime of the functions.",
459 "The input type of the profunctor.",
460 "The output type of the profunctor.",
461 "The type of the `Err` variant (threaded through)."
462 )]
463 ///
464 #[document_parameters("The `Reverse` instance to lift.")]
465 ///
466 #[document_returns("A `Reverse` instance operating on `Result` types.")]
467 ///
468 #[document_examples]
469 ///
470 /// ```
471 /// use fp_library::{
472 /// brands::{
473 /// RcBrand,
474 /// optics::*,
475 /// },
476 /// classes::profunctor::Choice,
477 /// types::optics::{
478 /// Forget,
479 /// Reverse,
480 /// },
481 /// };
482 ///
483 /// // rev wraps a getter transformer: (i32 -> i32) -> (i32 -> i32)
484 /// let rev = Reverse::<ForgetBrand<RcBrand, i32>, RcBrand, i32, i32, i32, i32>::new(
485 /// |f: Forget<'_, RcBrand, i32, i32, i32>| Forget::new(move |x: i32| f.run(x) + 1),
486 /// );
487 /// // right(rev).run(getter) = rev.run(unright(getter))
488 /// // unright wraps input in Ok: unright(|r| r.unwrap()) = identity
489 /// // rev.run(identity) = |x| x + 1
490 /// let result = <ReverseBrand<ForgetBrand<RcBrand, i32>, RcBrand, i32, i32> as Choice>::right::<
491 /// i32,
492 /// i32,
493 /// String,
494 /// >(rev);
495 /// let transformed = (result.run)(Forget::new(|r: Result<i32, String>| r.unwrap()));
496 /// assert_eq!(transformed.run(41), 42);
497 /// ```
498 fn right<'a, A: 'a, B: 'a, C: 'a>(
499 pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A, B>)
500 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, Result<A, C>, Result<B, C>>)
501 {
502 let r = pab.run;
503 Reverse::new(move |p| (*r)(InnerP::unright(p)))
504 }
505 }
506
507 /// `Costrong` instance for `ReverseBrand<InnerP, OuterP, S, T>` whenever `InnerP: Strong`.
508 ///
509 /// Corresponds to:
510 /// ```purescript
511 /// instance strongRe :: Strong p => Costrong (Re p s t) where
512 /// unfirst (Re r) = Re (r <<< first)
513 /// unsecond (Re r) = Re (r <<< second)
514 /// ```
515 #[document_type_parameters(
516 "The inner `Strong` profunctor brand.",
517 "The outer cloneable function pointer brand.",
518 "The fixed source type.",
519 "The fixed target type."
520 )]
521 impl<InnerP: Strong + 'static, PointerBrand: ToDynCloneFn + 'static, S: 'static, T: 'static>
522 Costrong for ReverseBrand<InnerP, PointerBrand, S, T>
523 {
524 /// Extracts from a `Reverse` that operates on the first component of a pair using `InnerP::first`.
525 #[document_signature]
526 ///
527 #[document_type_parameters(
528 "The lifetime of the functions.",
529 "The input type of the resulting `Reverse`.",
530 "The output type of the resulting `Reverse`.",
531 "The type of the second component (threaded through)."
532 )]
533 ///
534 #[document_parameters("The `Reverse` instance operating on pair types.")]
535 ///
536 #[document_returns("A `Reverse` instance operating on the unwrapped types.")]
537 ///
538 #[document_examples]
539 ///
540 /// ```
541 /// use fp_library::{
542 /// brands::{
543 /// RcBrand,
544 /// RcFnBrand,
545 /// optics::*,
546 /// },
547 /// classes::{
548 /// clone_fn::new as lift_fn_new,
549 /// profunctor::Costrong,
550 /// },
551 /// types::optics::Reverse,
552 /// };
553 ///
554 /// // rev.run: Rc<dyn Fn((i32, String)) -> (i32, String)> -> Rc<dyn Fn(i32) -> i32>
555 /// let rev = Reverse::<RcFnBrand, RcBrand, i32, i32, (i32, String), (i32, String)>::new(
556 /// |f: std::rc::Rc<dyn Fn((i32, String)) -> (i32, String)>| {
557 /// lift_fn_new::<RcFnBrand, _, _>(move |x: i32| f((x, String::new())).0)
558 /// },
559 /// );
560 /// // unfirst(rev).run(g) = rev.run(RcFnBrand::first(g))
561 /// // where RcFnBrand::first(g)((x, s)) = (g(x), s)
562 /// // so rev.run(first(g))(x) = first(g)((x, "")).0 = g(x)
563 /// let result =
564 /// <ReverseBrand<RcFnBrand, RcBrand, i32, i32> as Costrong>::unfirst::<i32, i32, String>(rev);
565 /// let add_one = lift_fn_new::<RcFnBrand, i32, i32>(|x: i32| x + 1);
566 /// assert_eq!(((result.run)(add_one))(41), 42);
567 /// ```
568 fn unfirst<'a, A: 'a, B: 'a, C: 'a>(
569 pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, (A, C), (B, C)>)
570 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A, B>) {
571 let r = pab.run;
572 Reverse::new(move |pba| (*r)(InnerP::first(pba)))
573 }
574
575 /// Extracts from a `Reverse` that operates on the second component of a pair using `InnerP::second`.
576 #[document_signature]
577 ///
578 #[document_type_parameters(
579 "The lifetime of the functions.",
580 "The input type of the resulting `Reverse`.",
581 "The output type of the resulting `Reverse`.",
582 "The type of the first component (threaded through)."
583 )]
584 ///
585 #[document_parameters("The `Reverse` instance operating on pair types.")]
586 ///
587 #[document_returns("A `Reverse` instance operating on the unwrapped types.")]
588 ///
589 #[document_examples]
590 ///
591 /// ```
592 /// use fp_library::{
593 /// brands::{
594 /// RcBrand,
595 /// RcFnBrand,
596 /// optics::*,
597 /// },
598 /// classes::{
599 /// clone_fn::new as lift_fn_new,
600 /// profunctor::Costrong,
601 /// },
602 /// types::optics::Reverse,
603 /// };
604 ///
605 /// // rev.run: Rc<dyn Fn((String, i32)) -> (String, i32)> -> Rc<dyn Fn(i32) -> i32>
606 /// let rev = Reverse::<RcFnBrand, RcBrand, i32, i32, (String, i32), (String, i32)>::new(
607 /// |f: std::rc::Rc<dyn Fn((String, i32)) -> (String, i32)>| {
608 /// lift_fn_new::<RcFnBrand, _, _>(move |x: i32| f((String::new(), x)).1)
609 /// },
610 /// );
611 /// // unsecond(rev).run(g) = rev.run(RcFnBrand::second(g))
612 /// // where RcFnBrand::second(g)((s, x)) = (s, g(x))
613 /// // so rev.run(second(g))(x) = second(g)(("", x)).1 = g(x)
614 /// let result =
615 /// <ReverseBrand<RcFnBrand, RcBrand, i32, i32> as Costrong>::unsecond::<i32, i32, String>(rev);
616 /// let add_one = lift_fn_new::<RcFnBrand, i32, i32>(|x: i32| x + 1);
617 /// assert_eq!(((result.run)(add_one))(41), 42);
618 /// ```
619 fn unsecond<'a, A: 'a, B: 'a, C: 'a>(
620 pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, (C, A), (C, B)>)
621 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A, B>) {
622 let r = pab.run;
623 Reverse::new(move |pba| (*r)(InnerP::second(pba)))
624 }
625 }
626
627 /// `Strong` instance for `ReverseBrand<InnerP, OuterP, S, T>` whenever `InnerP: Costrong`.
628 ///
629 /// Corresponds to:
630 /// ```purescript
631 /// instance costrongRe :: Costrong p => Strong (Re p s t) where
632 /// first (Re r) = Re (r <<< unfirst)
633 /// second (Re r) = Re (r <<< unsecond)
634 /// ```
635 #[document_type_parameters(
636 "The inner `Costrong` profunctor brand.",
637 "The outer cloneable function pointer brand.",
638 "The fixed source type.",
639 "The fixed target type."
640 )]
641 impl<InnerP: Costrong + 'static, PointerBrand: ToDynCloneFn + 'static, S: 'static, T: 'static>
642 Strong for ReverseBrand<InnerP, PointerBrand, S, T>
643 {
644 /// Lifts `Reverse` to operate on the first component of a pair using `InnerP::unfirst`.
645 #[document_signature]
646 ///
647 #[document_type_parameters(
648 "The lifetime of the functions.",
649 "The input type of the profunctor.",
650 "The output type of the profunctor.",
651 "The type of the second component (threaded through)."
652 )]
653 ///
654 #[document_parameters("The `Reverse` instance to lift.")]
655 ///
656 #[document_returns("A `Reverse` instance operating on pair types.")]
657 ///
658 #[document_examples]
659 ///
660 /// ```
661 /// use fp_library::{
662 /// brands::{
663 /// RcBrand,
664 /// RcFnBrand,
665 /// optics::*,
666 /// },
667 /// classes::profunctor::Strong,
668 /// types::optics::{
669 /// Reverse,
670 /// Tagged,
671 /// },
672 /// };
673 ///
674 /// // rev.run: Tagged<i32, i32> -> Tagged<i32, i32>
675 /// let rev = Reverse::<TaggedBrand, RcBrand, i32, i32, i32, i32>::new(|t: Tagged<i32, i32>| {
676 /// Tagged::new(t.0 + 1)
677 /// });
678 /// // first(rev).run(Tagged((41, "hi"))) = rev.run(TaggedBrand::unfirst(Tagged((41, "hi"))))
679 /// // = rev.run(Tagged(41)) = Tagged(42)
680 /// let result =
681 /// <ReverseBrand<TaggedBrand, RcBrand, i32, i32> as Strong>::first::<i32, i32, &str>(rev);
682 /// assert_eq!((result.run)(Tagged::<(i32, &str), (i32, &str)>::new((41, "hi"))).0, 42);
683 /// ```
684 fn first<'a, A: 'a, B: 'a, C: 'a>(
685 pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A, B>)
686 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, (A, C), (B, C)>) {
687 let r = pab.run;
688 Reverse::new(move |p| (*r)(InnerP::unfirst(p)))
689 }
690
691 /// Lifts `Reverse` to operate on the second component of a pair using `InnerP::unsecond`.
692 #[document_signature]
693 ///
694 #[document_type_parameters(
695 "The lifetime of the functions.",
696 "The input type of the profunctor.",
697 "The output type of the profunctor.",
698 "The type of the first component (threaded through)."
699 )]
700 ///
701 #[document_parameters("The `Reverse` instance to lift.")]
702 ///
703 #[document_returns("A `Reverse` instance operating on pair types.")]
704 ///
705 #[document_examples]
706 ///
707 /// ```
708 /// use fp_library::{
709 /// brands::{
710 /// RcBrand,
711 /// RcFnBrand,
712 /// optics::*,
713 /// },
714 /// classes::profunctor::Strong,
715 /// types::optics::{
716 /// Reverse,
717 /// Tagged,
718 /// },
719 /// };
720 ///
721 /// // rev.run: Tagged<i32, i32> -> Tagged<i32, i32>
722 /// let rev = Reverse::<TaggedBrand, RcBrand, i32, i32, i32, i32>::new(|t: Tagged<i32, i32>| {
723 /// Tagged::new(t.0 + 1)
724 /// });
725 /// // second(rev).run(Tagged(("hi", 41))) = rev.run(TaggedBrand::unsecond(Tagged(("hi", 41))))
726 /// // = rev.run(Tagged(41)) = Tagged(42)
727 /// let result =
728 /// <ReverseBrand<TaggedBrand, RcBrand, i32, i32> as Strong>::second::<i32, i32, &str>(rev);
729 /// assert_eq!((result.run)(Tagged::<(&str, i32), (&str, i32)>::new(("hi", 41))).0, 42);
730 /// ```
731 fn second<'a, A: 'a, B: 'a, C: 'a>(
732 pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A, B>)
733 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, (C, A), (C, B)>) {
734 let r = pab.run;
735 Reverse::new(move |p| (*r)(InnerP::unsecond(p)))
736 }
737 }
738
739 /// A reversed optic, produced by the [`reverse`] combinator.
740 ///
741 /// `ReversedOptic` wraps an inner optic and implements reversed optic traits by
742 /// evaluating the inner optic with `ReverseBrand<ConcreteP>` as the profunctor.
743 ///
744 /// Corresponds to PureScript's `re :: Optic (Re p a b) s t a b -> Optic p b a t s`.
745 ///
746 /// The reversed optic swaps the roles of source/target and focus types:
747 /// - An optic `S -> T, A -> B` becomes `B -> A, T -> S` (for review)
748 /// - A simple optic `S <-> A` becomes `A <-> S` (for getter/fold)
749 #[document_type_parameters(
750 "The lifetime of the values.",
751 "The cloneable function pointer brand used by the `Reverse` profunctor.",
752 "The source type of the original optic.",
753 "The target type of the original optic.",
754 "The focus source type of the original optic.",
755 "The focus target type of the original optic.",
756 "The inner optic type."
757 )]
758 pub struct ReversedOptic<'a, PointerBrand, S, T, A, B, O>
759 where
760 PointerBrand: ToDynCloneFn,
761 S: 'a,
762 T: 'a,
763 A: 'a,
764 B: 'a, {
765 inner: O,
766 _phantom: PhantomData<(&'a (), PointerBrand, S, T, A, B)>,
767 }
768
769 /// Reverses an optic using the `Reverse` profunctor.
770 ///
771 /// Given an optic from `S -> T` focusing on `A -> B`, produces a reversed optic
772 /// that can be used as:
773 /// - An [`IsoOptic`] from `B, A` to `T, S` (when the inner optic implements [`IsoOptic`])
774 /// - A [`ReviewOptic`] from `B -> A` focusing on `T -> S` (when the inner optic
775 /// implements [`LensOptic`] - covers isos and lenses)
776 /// - A [`GetterOptic`] from `A` to `S` (when the inner optic implements [`PrismOptic`]
777 /// with simple types `S = T, A = B`)
778 /// - A [`FoldOptic`] from `A` to `S` (same conditions as getter)
779 ///
780 /// Corresponds to PureScript's `re t = unwrap (t (Reverse identity))`.
781 #[document_signature]
782 ///
783 #[document_type_parameters(
784 "The lifetime of the values.",
785 "The cloneable function pointer brand.",
786 "The source type of the original optic.",
787 "The target type of the original optic.",
788 "The focus source type of the original optic.",
789 "The focus target type of the original optic.",
790 "The inner optic type."
791 )]
792 ///
793 #[document_parameters("The optic to reverse.")]
794 ///
795 #[document_returns("A [`ReversedOptic`] wrapping the inner optic.")]
796 ///
797 #[document_examples]
798 ///
799 /// ```
800 /// use fp_library::{
801 /// brands::{
802 /// optics::*,
803 /// *,
804 /// },
805 /// classes::optics::ReviewOptic,
806 /// types::optics::{
807 /// LensPrime,
808 /// Tagged,
809 /// reverse,
810 /// },
811 /// };
812 ///
813 /// // Create a lens for (i32, String) focusing on the first element
814 /// let fst: LensPrime<RcBrand, (i32, String), i32> =
815 /// LensPrime::from_view_set(|(x, _)| x, |((_, s), x)| (x, s));
816 ///
817 /// // Reverse it to get a ReviewOptic
818 /// let reversed = reverse::<RcBrand, _, _, _, _, _>(fst);
819 ///
820 /// // Use ReviewOptic: given a Tagged<(i32, String), (i32, String)>, produce Tagged<i32, i32>
821 /// let result = ReviewOptic::evaluate(&reversed, Tagged::new((42, "hello".to_string())));
822 /// assert_eq!(result.0, 42);
823 /// ```
824 pub fn reverse<'a, PointerBrand, S, T, A, B, O>(
825 optic: O
826 ) -> ReversedOptic<'a, PointerBrand, S, T, A, B, O>
827 where
828 PointerBrand: ToDynCloneFn,
829 S: 'a,
830 T: 'a,
831 A: 'a,
832 B: 'a, {
833 ReversedOptic {
834 inner: optic,
835 _phantom: PhantomData,
836 }
837 }
838
839 /// `ReviewOptic` for `ReversedOptic` - reversing any optic >= `Lens`.
840 ///
841 /// `ReverseBrand<TaggedBrand>` has `Strong` (from `TaggedBrand: Costrong`),
842 /// satisfying the `P: Strong` bound required by [`LensOptic::evaluate`].
843 ///
844 /// This covers `Iso` and `Lens`, matching the PureScript semantics where
845 /// `Re Tagged` has `Strong` (from `Tagged: Costrong`) but not `Choice`
846 /// (since `Tagged` does not implement `Cochoice`).
847 #[document_type_parameters(
848 "The lifetime of the values.",
849 "The cloneable function pointer brand.",
850 "The source type of the original optic.",
851 "The target type of the original optic.",
852 "The focus source type of the original optic.",
853 "The focus target type of the original optic.",
854 "The inner optic type."
855 )]
856 #[document_parameters("The reversed optic instance.")]
857 impl<'a, PointerBrand, S, T, A, B, O> ReviewOptic<'a, B, A, T, S>
858 for ReversedOptic<'a, PointerBrand, S, T, A, B, O>
859 where
860 PointerBrand: ToDynCloneFn + 'static,
861 O: LensOptic<'a, S, T, A, B>,
862 S: 'a + 'static,
863 T: 'a + 'static,
864 A: 'a + 'static,
865 B: 'a + 'static,
866 {
867 /// Evaluates the reversed optic with `Tagged`, producing a review in the reverse direction.
868 #[document_signature]
869 #[document_parameters("The tagged profunctor value.")]
870 #[document_returns("The transformed tagged profunctor value.")]
871 #[document_examples]
872 ///
873 /// ```
874 /// use fp_library::{
875 /// brands::{
876 /// optics::*,
877 /// *,
878 /// },
879 /// classes::optics::ReviewOptic,
880 /// types::optics::{
881 /// LensPrime,
882 /// Tagged,
883 /// reverse,
884 /// },
885 /// };
886 ///
887 /// // reverse(lens) as a review: given the source, extracts the focus.
888 /// let lens: LensPrime<RcBrand, (i32, String), i32> =
889 /// LensPrime::from_view_set(|(x, _)| x, |((_, s), x)| (x, s));
890 /// let reversed = reverse::<RcBrand, _, _, _, _, _>(lens);
891 /// let result = ReviewOptic::evaluate(&reversed, Tagged::new((42, "hello".to_string())));
892 /// assert_eq!(result.0, 42);
893 /// ```
894 fn evaluate(
895 &self,
896 pab: Apply!(<TaggedBrand as Kind!( type Of<'b, X: 'b, Y: 'b>: 'b; )>::Of<'a, T, S>),
897 ) -> Apply!(<TaggedBrand as Kind!( type Of<'b, X: 'b, Y: 'b>: 'b; )>::Of<'a, B, A>) {
898 // Reverse identity: Reverse<TaggedBrand, PB, A, B, A, B>
899 // wraps Tagged<B, A> -> Tagged<B, A> (identity)
900 let rev_identity = Reverse::<TaggedBrand, PointerBrand, A, B, A, B>::new(|x| x);
901 // Evaluate inner optic with P = ReverseBrand<TaggedBrand, PB, A, B>
902 // ReverseBrand<TaggedBrand> has Strong (from TaggedBrand: Costrong),
903 // satisfying LensOptic's P: Strong bound.
904 // Input: P::Of<A, B> = Reverse<TaggedBrand, PB, A, B, A, B> (our identity)
905 // Output: P::Of<S, T> = Reverse<TaggedBrand, PB, A, B, S, T>
906 let result =
907 self.inner.evaluate::<ReverseBrand<TaggedBrand, PointerBrand, A, B>>(rev_identity);
908 // Reverse<TaggedBrand, PB, A, B, S, T> wraps Tagged<T, S> -> Tagged<B, A>
909 (result.run)(pab)
910 }
911 }
912
913 /// `IsoOptic` for `ReversedOptic` - reversing an iso to an iso.
914 ///
915 /// `ReverseBrand<P>` has `Profunctor` whenever `P: Profunctor`, which is all that
916 /// [`IsoOptic::evaluate`] requires. This means `reverse(iso)` is itself an iso,
917 /// matching the PureScript semantics where `re :: Iso s t a b -> Iso b a t s`.
918 #[document_type_parameters(
919 "The lifetime of the values.",
920 "The cloneable function pointer brand.",
921 "The source type of the original optic.",
922 "The target type of the original optic.",
923 "The focus source type of the original optic.",
924 "The focus target type of the original optic.",
925 "The inner optic type."
926 )]
927 #[document_parameters("The reversed optic instance.")]
928 impl<'a, PointerBrand, S, T, A, B, O> IsoOptic<'a, B, A, T, S>
929 for ReversedOptic<'a, PointerBrand, S, T, A, B, O>
930 where
931 PointerBrand: ToDynCloneFn + 'static,
932 O: IsoOptic<'a, S, T, A, B>,
933 S: 'a + 'static,
934 T: 'a + 'static,
935 A: 'a + 'static,
936 B: 'a + 'static,
937 {
938 /// Evaluates the reversed optic with any profunctor, producing an iso in the reverse direction.
939 #[document_signature]
940 #[document_type_parameters("The profunctor type.")]
941 #[document_parameters("The profunctor value to transform.")]
942 #[document_returns("The transformed profunctor value.")]
943 #[document_examples]
944 ///
945 /// ```
946 /// use fp_library::{
947 /// brands::{
948 /// optics::*,
949 /// *,
950 /// },
951 /// classes::optics::IsoOptic,
952 /// functions::lift_fn_new,
953 /// types::optics::{
954 /// IsoPrime,
955 /// reverse,
956 /// },
957 /// };
958 ///
959 /// // An iso between (i32,) and i32
960 /// let iso: IsoPrime<RcBrand, (i32,), i32> = IsoPrime::new(|(x,)| x, |x| (x,));
961 /// let reversed = reverse::<RcBrand, _, _, _, _, _>(iso);
962 /// // reverse(iso) is itself an iso from i32 to (i32,)
963 /// let f = lift_fn_new::<RcFnBrand, _, _>(|(x,): (i32,)| (x * 2,));
964 /// let modifier = IsoOptic::evaluate::<RcFnBrand>(&reversed, f);
965 /// assert_eq!(modifier(21), 42);
966 /// ```
967 fn evaluate<P: Profunctor + 'static>(
968 &self,
969 pab: Apply!(<P as Kind!( type Of<'b, X: 'b, Y: 'b>: 'b; )>::Of<'a, T, S>),
970 ) -> Apply!(<P as Kind!( type Of<'b, X: 'b, Y: 'b>: 'b; )>::Of<'a, B, A>) {
971 // Reverse identity: Reverse<P, PB, A, B, A, B>
972 // wraps P::Of<B, A> -> P::Of<B, A> (identity)
973 let rev_identity = Reverse::<P, PointerBrand, A, B, A, B>::new(|x| x);
974 // Evaluate inner iso with ReverseBrand<P, PB, A, B>
975 // IsoOptic::evaluate needs Profunctor, and ReverseBrand<P>: Profunctor when P: Profunctor
976 let result = self.inner.evaluate::<ReverseBrand<P, PointerBrand, A, B>>(rev_identity);
977 // Reverse<P, PB, A, B, S, T> wraps P::Of<T, S> -> P::Of<B, A>
978 (result.run)(pab)
979 }
980 }
981
982 /// `GetterOptic` for `ReversedOptic` - reversing prism-like optics to getters.
983 ///
984 /// `ReverseBrand<ForgetBrand<Q, R>>` has `Choice` (from `ForgetBrand: Cochoice`)
985 /// but NOT `Strong` (since `ForgetBrand` is not `Costrong`), so only
986 /// [`PrismOptic`]'s `P: Choice` bound can be satisfied.
987 ///
988 /// This means `reverse(prism)` and `reverse(iso)` produce getters, but `reverse(lens)` does not.
989 /// This matches PureScript semantics.
990 #[document_type_parameters(
991 "The lifetime of the values.",
992 "The cloneable function pointer brand.",
993 "The source type of the original (simple) optic.",
994 "The focus type of the original (simple) optic.",
995 "The inner optic type."
996 )]
997 #[document_parameters("The reversed optic instance.")]
998 impl<'a, PointerBrand, S, A, O> GetterOptic<'a, A, S>
999 for ReversedOptic<'a, PointerBrand, S, S, A, A, O>
1000 where
1001 PointerBrand: ToDynCloneFn + 'static,
1002 O: PrismOptic<'a, S, S, A, A>,
1003 S: 'a + 'static,
1004 A: 'a + 'static,
1005 {
1006 /// Evaluates the reversed optic with `Forget`, producing a getter in the reverse direction.
1007 #[document_signature]
1008 #[document_type_parameters(
1009 "The return type of the forget profunctor.",
1010 "The reference-counted pointer type."
1011 )]
1012 #[document_parameters("The forget profunctor value.")]
1013 #[document_returns("The transformed forget profunctor value.")]
1014 #[document_examples]
1015 ///
1016 /// ```
1017 /// use fp_library::{
1018 /// brands::{
1019 /// optics::*,
1020 /// *,
1021 /// },
1022 /// classes::optics::GetterOptic,
1023 /// types::optics::{
1024 /// Forget,
1025 /// PrismPrime,
1026 /// reverse,
1027 /// },
1028 /// };
1029 ///
1030 /// // reverse(prism) as a getter: given A, extract S via the prism's review
1031 /// let some_prism: PrismPrime<RcBrand, Option<i32>, i32> = PrismPrime::from_option(|o| o, Some);
1032 /// let reversed = reverse::<RcBrand, _, _, _, _, _>(some_prism);
1033 /// let forget = Forget::<RcBrand, Option<i32>, Option<i32>, Option<i32>>::new(|o| o);
1034 /// let result = GetterOptic::evaluate::<Option<i32>, RcBrand>(&reversed, forget);
1035 /// assert_eq!(result.run(42), Some(42));
1036 /// ```
1037 fn evaluate<R: 'a + 'static, Q: ToDynCloneFn + 'static>(
1038 &self,
1039 pab: Apply!(<ForgetBrand<Q, R> as Kind!( type Of<'b, X: 'b, Y: 'b>: 'b; )>::Of<'a, S, S>),
1040 ) -> Apply!(<ForgetBrand<Q, R> as Kind!( type Of<'b, X: 'b, Y: 'b>: 'b; )>::Of<'a, A, A>)
1041 {
1042 // Reverse identity: Reverse<ForgetBrand<Q, R>, PB, A, A, A, A>
1043 // wraps Forget<Q, R, A, A> -> Forget<Q, R, A, A> (identity)
1044 let rev_identity = Reverse::<ForgetBrand<Q, R>, PointerBrand, A, A, A, A>::new(|x| x);
1045 // Evaluate inner optic with P = ReverseBrand<ForgetBrand<Q, R>, PB, A, A>
1046 // Input: P::Of<A, A> = Reverse<ForgetBrand<Q, R>, PB, A, A, A, A> (our identity)
1047 // Output: P::Of<S, S> = Reverse<ForgetBrand<Q, R>, PB, A, A, S, S>
1048 let result = self
1049 .inner
1050 .evaluate::<ReverseBrand<ForgetBrand<Q, R>, PointerBrand, A, A>>(rev_identity);
1051 // Reverse<ForgetBrand<Q, R>, PB, A, A, S, S> wraps Forget<Q, R, S, S> -> Forget<Q, R, A, A>
1052 (result.run)(pab)
1053 }
1054 }
1055
1056 /// `FoldOptic` for `ReversedOptic` - reversing prism-like optics to folds.
1057 ///
1058 /// Same as the [`GetterOptic`] implementation but with the additional `R: Monoid + Clone` bound
1059 /// required by [`FoldOptic`].
1060 #[document_type_parameters(
1061 "The lifetime of the values.",
1062 "The cloneable function pointer brand.",
1063 "The source type of the original (simple) optic.",
1064 "The focus type of the original (simple) optic.",
1065 "The inner optic type."
1066 )]
1067 #[document_parameters("The reversed optic instance.")]
1068 impl<'a, PointerBrand, S, A, O> FoldOptic<'a, A, S>
1069 for ReversedOptic<'a, PointerBrand, S, S, A, A, O>
1070 where
1071 PointerBrand: ToDynCloneFn + 'static,
1072 O: PrismOptic<'a, S, S, A, A>,
1073 S: 'a + 'static,
1074 A: 'a + 'static,
1075 {
1076 /// Evaluates the reversed optic with `Forget` for a monoidal fold in the reverse direction.
1077 #[document_signature]
1078 #[document_type_parameters("The monoid type.", "The reference-counted pointer type.")]
1079 #[document_parameters("The forget profunctor value.")]
1080 #[document_returns("The transformed forget profunctor value.")]
1081 #[document_examples]
1082 ///
1083 /// ```
1084 /// use fp_library::{
1085 /// brands::{
1086 /// optics::*,
1087 /// *,
1088 /// },
1089 /// classes::optics::FoldOptic,
1090 /// types::optics::{
1091 /// Forget,
1092 /// PrismPrime,
1093 /// reverse,
1094 /// },
1095 /// };
1096 ///
1097 /// // reverse(prism) as a fold with String monoid
1098 /// let some_prism: PrismPrime<RcBrand, Option<i32>, i32> = PrismPrime::from_option(|o| o, Some);
1099 /// let reversed = reverse::<RcBrand, _, _, _, _, _>(some_prism);
1100 /// let forget = Forget::<RcBrand, String, Option<i32>, Option<i32>>::new(|o: Option<i32>| {
1101 /// format!("{:?}", o)
1102 /// });
1103 /// let result = FoldOptic::evaluate::<String, RcBrand>(&reversed, forget);
1104 /// assert_eq!(result.run(42), "Some(42)");
1105 /// ```
1106 fn evaluate<R: 'a + Monoid + Clone + 'static, Q: ToDynCloneFn + 'static>(
1107 &self,
1108 pab: Apply!(<ForgetBrand<Q, R> as Kind!( type Of<'b, X: 'b, Y: 'b>: 'b; )>::Of<'a, S, S>),
1109 ) -> Apply!(<ForgetBrand<Q, R> as Kind!( type Of<'b, X: 'b, Y: 'b>: 'b; )>::Of<'a, A, A>)
1110 {
1111 let rev_identity = Reverse::<ForgetBrand<Q, R>, PointerBrand, A, A, A, A>::new(|x| x);
1112 let result = self
1113 .inner
1114 .evaluate::<ReverseBrand<ForgetBrand<Q, R>, PointerBrand, A, A>>(rev_identity);
1115 (result.run)(pab)
1116 }
1117 }
1118}
1119pub use inner::*;