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