Skip to main content

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