Skip to main content

fp_library/types/optics/
iso.rs

1//! Isomorphism optics for bidirectional conversions.
2
3#[fp_macros::document_module]
4mod inner {
5	use {
6		crate::{
7			Apply,
8			brands::{
9				FnBrand,
10				optics::*,
11			},
12			classes::{
13				monoid::Monoid,
14				optics::*,
15				profunctor::{
16					Choice,
17					Closed,
18					Profunctor,
19					Strong,
20					Wander,
21				},
22				*,
23			},
24			kinds::*,
25			types::optics::Tagged,
26		},
27		fp_macros::*,
28	};
29
30	/// A polymorphic isomorphism where types can change.
31	/// This matches PureScript's `Iso s t a b`.
32	///
33	/// An isomorphism represents a lossless bidirectional conversion between types.
34	/// Uses [`FnBrand`](crate::brands::FnBrand) to support capturing closures.
35	#[document_type_parameters(
36		"The lifetime of the values.",
37		"The reference-counted pointer type.",
38		"The source type of the structure.",
39		"The target type of the structure after an update.",
40		"The source type of the focus.",
41		"The target type of the focus after an update."
42	)]
43	pub struct Iso<'a, PointerBrand, S, T, A, B>
44	where
45		PointerBrand: UnsizedCoercible,
46		S: 'a,
47		T: 'a,
48		A: 'a,
49		B: 'a, {
50		/// Forward conversion: from structure to focus.
51		pub from: Apply!(<FnBrand<PointerBrand> as Kind!( type Of<'b, U: 'b, V: 'b>: 'b; )>::Of<'a, S, A>),
52		/// Backward conversion: from focus to structure.
53		pub to: Apply!(<FnBrand<PointerBrand> as Kind!( type Of<'b, U: 'b, V: 'b>: 'b; )>::Of<'a, B, T>),
54	}
55
56	#[document_type_parameters(
57		"The lifetime of the values.",
58		"The reference-counted pointer type.",
59		"The source type of the structure.",
60		"The target type of the structure after an update.",
61		"The source type of the focus.",
62		"The target type of the focus after an update."
63	)]
64	#[document_parameters("The iso instance.")]
65	impl<'a, PointerBrand, S, T, A, B> Clone for Iso<'a, PointerBrand, S, T, A, B>
66	where
67		PointerBrand: UnsizedCoercible,
68		S: 'a,
69		T: 'a,
70		A: 'a,
71		B: 'a,
72	{
73		#[document_signature]
74		#[document_returns("A new `Iso` instance that is a copy of the original.")]
75		#[document_examples]
76		///
77		/// ```
78		/// use fp_library::{
79		/// 	brands::RcBrand,
80		/// 	types::optics::Iso,
81		/// };
82		///
83		/// let string_chars: Iso<RcBrand, String, String, Vec<char>, Vec<char>> =
84		/// 	Iso::new(|s: String| s.chars().collect(), |v: Vec<char>| v.into_iter().collect());
85		/// let cloned = string_chars.clone();
86		/// assert_eq!(cloned.from("hi".to_string()), vec!['h', 'i']);
87		/// ```
88		fn clone(&self) -> Self {
89			Iso {
90				from: self.from.clone(),
91				to: self.to.clone(),
92			}
93		}
94	}
95
96	#[document_type_parameters(
97		"The lifetime of the values.",
98		"The reference-counted pointer type.",
99		"The source type of the structure.",
100		"The target type of the structure after an update.",
101		"The source type of the focus.",
102		"The target type of the focus after an update."
103	)]
104	#[document_parameters("The iso instance.")]
105	impl<'a, PointerBrand, S: 'a, T: 'a, A: 'a, B: 'a> Iso<'a, PointerBrand, S, T, A, B>
106	where
107		PointerBrand: UnsizedCoercible,
108	{
109		/// Create a new polymorphic isomorphism.
110		#[document_signature]
111		///
112		#[document_parameters(
113			"The forward conversion function.",
114			"The backward conversion function."
115		)]
116		///
117		#[document_returns("A new instance of the type.")]
118		#[document_examples]
119		///
120		/// ```
121		/// use fp_library::{
122		/// 	brands::RcBrand,
123		/// 	types::optics::Iso,
124		/// };
125		///
126		/// // Iso between String and Vec<char>
127		/// let string_chars: Iso<RcBrand, String, String, Vec<char>, Vec<char>> =
128		/// 	Iso::new(|s: String| s.chars().collect(), |v: Vec<char>| v.into_iter().collect());
129		/// assert_eq!(string_chars.from("hi".to_string()), vec!['h', 'i']);
130		/// ```
131		pub fn new(
132			from: impl 'a + Fn(S) -> A,
133			to: impl 'a + Fn(B) -> T,
134		) -> Self {
135			Iso {
136				from: <FnBrand<PointerBrand> as LiftFn>::new(from),
137				to: <FnBrand<PointerBrand> as LiftFn>::new(to),
138			}
139		}
140
141		/// Apply the forward conversion.
142		#[document_signature]
143		///
144		#[document_parameters("The structure to convert.")]
145		///
146		#[document_returns("The focus value.")]
147		///
148		#[document_examples]
149		///
150		/// ```
151		/// use fp_library::{
152		/// 	brands::RcBrand,
153		/// 	types::optics::Iso,
154		/// };
155		///
156		/// let string_chars: Iso<RcBrand, String, String, Vec<char>, Vec<char>> =
157		/// 	Iso::new(|s: String| s.chars().collect(), |v: Vec<char>| v.into_iter().collect());
158		/// let chars = string_chars.from("hello".to_string());
159		/// assert_eq!(chars, vec!['h', 'e', 'l', 'l', 'o']);
160		/// ```
161		pub fn from(
162			&self,
163			s: S,
164		) -> A {
165			(self.from)(s)
166		}
167
168		/// Apply the backward conversion.
169		#[document_signature]
170		///
171		#[document_parameters("The focus value to convert.")]
172		///
173		#[document_returns("The structure value.")]
174		///
175		#[document_examples]
176		///
177		/// ```
178		/// use fp_library::{
179		/// 	brands::RcBrand,
180		/// 	types::optics::Iso,
181		/// };
182		///
183		/// let string_chars: Iso<RcBrand, String, String, Vec<char>, Vec<char>> =
184		/// 	Iso::new(|s: String| s.chars().collect(), |v: Vec<char>| v.into_iter().collect());
185		/// let s = string_chars.to(vec!['h', 'i']);
186		/// assert_eq!(s, "hi");
187		/// ```
188		pub fn to(
189			&self,
190			b: B,
191		) -> T {
192			(self.to)(b)
193		}
194	}
195
196	#[document_type_parameters(
197		"The lifetime of the values.",
198		"The profunctor type.",
199		"The reference-counted pointer type.",
200		"The source type of the structure.",
201		"The target type of the structure after an update.",
202		"The source type of the focus.",
203		"The target type of the focus after an update."
204	)]
205	#[document_parameters("The iso instance.")]
206	impl<'a, Q, PointerBrand, S, T, A, B> Optic<'a, Q, S, T, A, B> for Iso<'a, PointerBrand, S, T, A, B>
207	where
208		Q: Profunctor,
209		PointerBrand: UnsizedCoercible,
210		S: 'a,
211		T: 'a,
212		A: 'a,
213		B: 'a,
214	{
215		#[document_signature]
216		#[document_parameters("The profunctor value to transform.")]
217		#[document_returns("The transformed profunctor value.")]
218		#[document_examples]
219		///
220		/// ```
221		/// use fp_library::{
222		/// 	brands::{
223		/// 		optics::*,
224		/// 		*,
225		/// 	},
226		/// 	classes::optics::*,
227		/// 	functions::*,
228		/// 	types::optics::*,
229		/// };
230		///
231		/// let iso: Iso<RcBrand, (i32,), (i32,), i32, i32> = Iso::new(|(x,)| x, |x| (x,));
232		/// let f = lift_fn_new::<RcFnBrand, _, _>(|x: i32| x + 1);
233		/// let modifier = Optic::<RcFnBrand, _, _, _, _>::evaluate(&iso, f);
234		/// assert_eq!(modifier((41,)), (42,));
235		/// ```
236		fn evaluate(
237			&self,
238			pab: Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, B>),
239		) -> Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, T>) {
240			let from = self.from.clone();
241			let to = self.to.clone();
242
243			// The Profunctor encoding of an Iso is:
244			// iso from to = dimap from to
245			Q::dimap(move |s| from(s), move |b| to(b), pab)
246		}
247	}
248
249	#[document_type_parameters(
250		"The lifetime of the values.",
251		"The reference-counted pointer type.",
252		"The source type of the structure.",
253		"The target type of the structure after an update.",
254		"The source type of the focus.",
255		"The target type of the focus after an update."
256	)]
257	#[document_parameters("The iso instance.")]
258	impl<'a, PointerBrand, S: 'a, T: 'a, A: 'a, B: 'a> IsoOptic<'a, S, T, A, B>
259		for Iso<'a, PointerBrand, S, T, A, B>
260	where
261		PointerBrand: UnsizedCoercible,
262	{
263		#[document_signature]
264		#[document_type_parameters("The profunctor type.")]
265		#[document_parameters("The profunctor value to transform.")]
266		#[document_returns("The transformed profunctor value.")]
267		#[document_examples]
268		///
269		/// ```
270		/// use fp_library::{
271		/// 	brands::{
272		/// 		optics::*,
273		/// 		*,
274		/// 	},
275		/// 	classes::optics::*,
276		/// 	functions::*,
277		/// 	types::optics::*,
278		/// };
279		///
280		/// let iso: Iso<RcBrand, (i32,), (i32,), i32, i32> = Iso::new(|(x,)| x, |x| (x,));
281		/// let f = lift_fn_new::<RcFnBrand, _, _>(|x: i32| x + 1);
282		/// let modifier: std::rc::Rc<dyn Fn((i32,)) -> (i32,)> = IsoOptic::evaluate::<RcFnBrand>(&iso, f);
283		/// assert_eq!(modifier((41,)), (42,));
284		/// ```
285		fn evaluate<Q: Profunctor + 'static>(
286			&self,
287			pab: Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, B>),
288		) -> Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, T>) {
289			Optic::<Q, S, T, A, B>::evaluate(self, pab)
290		}
291	}
292
293	#[document_type_parameters(
294		"The lifetime of the values.",
295		"The reference-counted pointer type.",
296		"The source type of the structure.",
297		"The target type of the structure after an update.",
298		"The source type of the focus.",
299		"The target type of the focus after an update."
300	)]
301	#[document_parameters("The iso instance.")]
302	impl<'a, PointerBrand, S: 'a, T: 'a, A: 'a, B: 'a> AffineTraversalOptic<'a, S, T, A, B>
303		for Iso<'a, PointerBrand, S, T, A, B>
304	where
305		PointerBrand: UnsizedCoercible,
306	{
307		#[document_signature]
308		#[document_type_parameters("The profunctor type.")]
309		#[document_parameters("The profunctor value to transform.")]
310		#[document_returns("The transformed profunctor value.")]
311		#[document_examples]
312		///
313		/// ```
314		/// use fp_library::{
315		/// 	brands::{
316		/// 		optics::*,
317		/// 		*,
318		/// 	},
319		/// 	classes::optics::*,
320		/// 	functions::*,
321		/// 	types::optics::*,
322		/// };
323		///
324		/// let iso: Iso<RcBrand, (i32,), (i32,), i32, i32> = Iso::new(|(x,)| x, |x| (x,));
325		/// let f = lift_fn_new::<RcFnBrand, _, _>(|x: i32| x + 1);
326		/// let modifier: std::rc::Rc<dyn Fn((i32,)) -> (i32,)> =
327		/// 	AffineTraversalOptic::evaluate::<RcFnBrand>(&iso, f);
328		/// assert_eq!(modifier((41,)), (42,));
329		/// ```
330		fn evaluate<Q: Strong + Choice>(
331			&self,
332			pab: Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, B>),
333		) -> Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, T>) {
334			Optic::<Q, S, T, A, B>::evaluate(self, pab)
335		}
336	}
337
338	#[document_type_parameters(
339		"The lifetime of the values.",
340		"The cloneable function brand used by the profunctor's `Closed` instance.",
341		"The reference-counted pointer type.",
342		"The source type of the structure.",
343		"The target type of the structure after an update.",
344		"The source type of the focus.",
345		"The target type of the focus after an update."
346	)]
347	#[document_parameters("The iso instance.")]
348	impl<'a, FunctionBrand: LiftFn, PointerBrand, S: 'a, T: 'a, A: 'a, B: 'a>
349		GrateOptic<'a, FunctionBrand, S, T, A, B> for Iso<'a, PointerBrand, S, T, A, B>
350	where
351		PointerBrand: UnsizedCoercible,
352	{
353		#[document_signature]
354		#[document_type_parameters("The profunctor type.")]
355		#[document_parameters("The profunctor value to transform.")]
356		#[document_returns("The transformed profunctor value.")]
357		#[document_examples]
358		///
359		/// ```
360		/// use fp_library::{
361		/// 	brands::{
362		/// 		optics::*,
363		/// 		*,
364		/// 	},
365		/// 	classes::optics::*,
366		/// 	functions::*,
367		/// 	types::optics::*,
368		/// };
369		///
370		/// let iso: Iso<RcBrand, (i32,), (i32,), i32, i32> = Iso::new(|(x,)| x, |x| (x,));
371		/// let f = lift_fn_new::<RcFnBrand, _, _>(|x: i32| x + 1);
372		/// let modifier: std::rc::Rc<dyn Fn((i32,)) -> (i32,)> =
373		/// 	GrateOptic::<RcFnBrand, _, _, _, _>::evaluate::<RcFnBrand>(&iso, f);
374		/// assert_eq!(modifier((41,)), (42,));
375		/// ```
376		fn evaluate<Q: Closed<FunctionBrand>>(
377			&self,
378			pab: Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, B>),
379		) -> Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, T>) {
380			Optic::<Q, S, T, A, B>::evaluate(self, pab)
381		}
382	}
383
384	#[document_type_parameters(
385		"The lifetime of the values.",
386		"The reference-counted pointer type.",
387		"The source type of the structure.",
388		"The target type of the structure after an update.",
389		"The source type of the focus.",
390		"The target type of the focus after an update."
391	)]
392	#[document_parameters("The iso instance.")]
393	impl<'a, PointerBrand, S: 'a, T: 'a, A: 'a, B: 'a> LensOptic<'a, S, T, A, B>
394		for Iso<'a, PointerBrand, S, T, A, B>
395	where
396		PointerBrand: UnsizedCoercible,
397	{
398		#[document_signature]
399		#[document_type_parameters("The profunctor type.")]
400		#[document_parameters("The profunctor value to transform.")]
401		#[document_returns("The transformed profunctor value.")]
402		#[document_examples]
403		///
404		/// ```
405		/// use fp_library::{
406		/// 	brands::{
407		/// 		optics::*,
408		/// 		*,
409		/// 	},
410		/// 	classes::optics::*,
411		/// 	functions::*,
412		/// 	types::optics::*,
413		/// };
414		///
415		/// let iso: Iso<RcBrand, (i32,), (i32,), i32, i32> = Iso::new(|(x,)| x, |x| (x,));
416		/// let f = lift_fn_new::<RcFnBrand, _, _>(|x: i32| x + 1);
417		/// let modifier: std::rc::Rc<dyn Fn((i32,)) -> (i32,)> = LensOptic::evaluate::<RcFnBrand>(&iso, f);
418		/// assert_eq!(modifier((41,)), (42,));
419		/// ```
420		fn evaluate<Q: Strong>(
421			&self,
422			pab: Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, B>),
423		) -> Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, T>) {
424			Optic::<Q, S, T, A, B>::evaluate(self, pab)
425		}
426	}
427
428	#[document_type_parameters(
429		"The lifetime of the values.",
430		"The reference-counted pointer type.",
431		"The source type of the structure.",
432		"The target type of the structure after an update.",
433		"The source type of the focus.",
434		"The target type of the focus after an update."
435	)]
436	#[document_parameters("The iso instance.")]
437	impl<'a, PointerBrand, S: 'a, T: 'a, A: 'a, B: 'a> PrismOptic<'a, S, T, A, B>
438		for Iso<'a, PointerBrand, S, T, A, B>
439	where
440		PointerBrand: UnsizedCoercible,
441	{
442		#[document_signature]
443		#[document_type_parameters("The profunctor type.")]
444		#[document_parameters("The profunctor value to transform.")]
445		#[document_returns("The transformed profunctor value.")]
446		#[document_examples]
447		///
448		/// ```
449		/// use fp_library::{
450		/// 	brands::{
451		/// 		optics::*,
452		/// 		*,
453		/// 	},
454		/// 	classes::optics::*,
455		/// 	functions::*,
456		/// 	types::optics::*,
457		/// };
458		///
459		/// let iso: Iso<RcBrand, (i32,), (i32,), i32, i32> = Iso::new(|(x,)| x, |x| (x,));
460		/// let f = lift_fn_new::<RcFnBrand, _, _>(|x: i32| x + 1);
461		/// let modifier: std::rc::Rc<dyn Fn((i32,)) -> (i32,)> =
462		/// 	PrismOptic::evaluate::<RcFnBrand>(&iso, f);
463		/// assert_eq!(modifier((41,)), (42,));
464		/// ```
465		fn evaluate<Q: Choice>(
466			&self,
467			pab: Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, B>),
468		) -> Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, T>) {
469			Optic::<Q, S, T, A, B>::evaluate(self, pab)
470		}
471	}
472
473	#[document_type_parameters(
474		"The lifetime of the values.",
475		"The reference-counted pointer type.",
476		"The source type of the structure.",
477		"The target type of the structure after an update.",
478		"The source type of the focus.",
479		"The target type of the focus after an update."
480	)]
481	#[document_parameters("The iso instance.")]
482	impl<'a, PointerBrand, S: 'a, T: 'a, A: 'a, B: 'a> TraversalOptic<'a, S, T, A, B>
483		for Iso<'a, PointerBrand, S, T, A, B>
484	where
485		PointerBrand: UnsizedCoercible,
486	{
487		#[document_signature]
488		#[document_type_parameters("The profunctor type.")]
489		#[document_parameters("The profunctor value to transform.")]
490		#[document_returns("The transformed profunctor value.")]
491		#[document_examples]
492		///
493		/// ```
494		/// use fp_library::{
495		/// 	brands::{
496		/// 		optics::*,
497		/// 		*,
498		/// 	},
499		/// 	classes::optics::*,
500		/// 	functions::*,
501		/// 	types::optics::*,
502		/// };
503		///
504		/// let iso: Iso<RcBrand, (i32,), (i32,), i32, i32> = Iso::new(|(x,)| x, |x| (x,));
505		/// let f = lift_fn_new::<RcFnBrand, _, _>(|x: i32| x + 1);
506		/// let modifier: std::rc::Rc<dyn Fn((i32,)) -> (i32,)> =
507		/// 	TraversalOptic::evaluate::<RcFnBrand>(&iso, f);
508		/// assert_eq!(modifier((41,)), (42,));
509		/// ```
510		fn evaluate<Q: Wander>(
511			&self,
512			pab: Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, B>),
513		) -> Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, T>) {
514			Optic::<Q, S, T, A, B>::evaluate(self, pab)
515		}
516	}
517
518	#[document_type_parameters(
519		"The lifetime of the values.",
520		"The reference-counted pointer type.",
521		"The source type of the structure.",
522		"The focus type."
523	)]
524	#[document_parameters("The iso instance.")]
525	impl<'a, PointerBrand, S: 'a, A: 'a> GetterOptic<'a, S, A> for Iso<'a, PointerBrand, S, S, A, A>
526	where
527		PointerBrand: UnsizedCoercible,
528	{
529		#[document_signature]
530		#[document_type_parameters(
531			"The return type of the forget profunctor.",
532			"The reference-counted pointer type."
533		)]
534		#[document_parameters("The profunctor value to transform.")]
535		#[document_returns("The transformed profunctor value.")]
536		#[document_examples]
537		///
538		/// ```
539		/// use fp_library::{
540		/// 	brands::{
541		/// 		optics::*,
542		/// 		*,
543		/// 	},
544		/// 	classes::optics::*,
545		/// 	functions::*,
546		/// 	types::optics::*,
547		/// };
548		///
549		/// let iso: Iso<RcBrand, (i32,), (i32,), i32, i32> = Iso::new(|(x,)| x, |x| (x,));
550		/// let f = Forget::<RcBrand, i32, i32, i32>::new(|x| x);
551		/// let folded = GetterOptic::evaluate(&iso, f);
552		/// assert_eq!(folded.run((42,)), 42);
553		/// ```
554		fn evaluate<R: 'a + 'static, Q: UnsizedCoercible + 'static>(
555			&self,
556			pab: Apply!(<ForgetBrand<Q, R> as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, A>),
557		) -> Apply!(<ForgetBrand<Q, R> as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, S>)
558		{
559			IsoOptic::evaluate::<ForgetBrand<Q, R>>(self, pab)
560		}
561	}
562
563	#[document_type_parameters(
564		"The lifetime of the values.",
565		"The reference-counted pointer type.",
566		"The source type of the structure.",
567		"The focus type."
568	)]
569	#[document_parameters("The iso instance.")]
570	impl<'a, PointerBrand, S: 'a, A: 'a> FoldOptic<'a, S, A> for Iso<'a, PointerBrand, S, S, A, A>
571	where
572		PointerBrand: UnsizedCoercible,
573	{
574		#[document_signature]
575		#[document_type_parameters("The monoid type.", "The reference-counted pointer type.")]
576		#[document_parameters("The profunctor value to transform.")]
577		#[document_returns("The transformed profunctor value.")]
578		#[document_examples]
579		///
580		/// ```
581		/// use fp_library::{
582		/// 	brands::{
583		/// 		optics::*,
584		/// 		*,
585		/// 	},
586		/// 	classes::optics::*,
587		/// 	functions::*,
588		/// 	types::optics::*,
589		/// };
590		///
591		/// let iso: Iso<RcBrand, (i32,), (i32,), i32, i32> = Iso::new(|(x,)| x, |x| (x,));
592		/// let f = Forget::<RcBrand, String, i32, i32>::new(|x| x.to_string());
593		/// let folded = FoldOptic::evaluate(&iso, f);
594		/// assert_eq!(folded.run((42,)), "42".to_string());
595		/// ```
596		fn evaluate<R: 'a + Monoid + 'static, Q: UnsizedCoercible + 'static>(
597			&self,
598			pab: Apply!(<ForgetBrand<Q, R> as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, A>),
599		) -> Apply!(<ForgetBrand<Q, R> as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, S>)
600		{
601			IsoOptic::evaluate::<ForgetBrand<Q, R>>(self, pab)
602		}
603	}
604
605	#[document_type_parameters(
606		"The lifetime of the values.",
607		"The reference-counted pointer type for the setter brand.",
608		"The reference-counted pointer type for the iso.",
609		"The source type of the structure.",
610		"The target type of the structure after an update.",
611		"The source type of the focus.",
612		"The target type of the focus after an update."
613	)]
614	#[document_parameters("The iso instance.")]
615	impl<'a, Q, PointerBrand, S: 'a, T: 'a, A: 'a, B: 'a> SetterOptic<'a, Q, S, T, A, B>
616		for Iso<'a, PointerBrand, S, T, A, B>
617	where
618		PointerBrand: UnsizedCoercible,
619		Q: UnsizedCoercible,
620	{
621		#[document_signature]
622		#[document_parameters("The profunctor value to transform.")]
623		#[document_returns("The transformed profunctor value.")]
624		#[document_examples]
625		///
626		/// ```
627		/// use fp_library::{
628		/// 	brands::{
629		/// 		optics::*,
630		/// 		*,
631		/// 	},
632		/// 	classes::optics::*,
633		/// 	functions::*,
634		/// 	types::optics::*,
635		/// };
636		///
637		/// let iso: Iso<RcBrand, (i32,), (i32,), i32, i32> = Iso::new(|(x,)| x, |x| (x,));
638		/// let f = lift_fn_new::<RcFnBrand, _, _>(|x: i32| x + 1);
639		/// let modifier: std::rc::Rc<dyn Fn((i32,)) -> (i32,)> =
640		/// 	SetterOptic::<RcBrand, _, _, _, _>::evaluate(&iso, f);
641		/// assert_eq!(modifier((41,)), (42,));
642		/// ```
643		fn evaluate(
644			&self,
645			pab: Apply!(<FnBrand<Q> as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, B>),
646		) -> Apply!(<FnBrand<Q> as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, T>) {
647			IsoOptic::evaluate::<FnBrand<Q>>(self, pab)
648		}
649	}
650
651	#[document_type_parameters(
652		"The lifetime of the values.",
653		"The reference-counted pointer type.",
654		"The source type of the structure.",
655		"The target type of the structure after an update.",
656		"The source type of the focus.",
657		"The target type of the focus after an update."
658	)]
659	#[document_parameters("The iso instance.")]
660	impl<'a, PointerBrand, S: 'a, T: 'a, A: 'a, B: 'a> ReviewOptic<'a, S, T, A, B>
661		for Iso<'a, PointerBrand, S, T, A, B>
662	where
663		PointerBrand: UnsizedCoercible,
664	{
665		#[document_signature]
666		#[document_parameters("The profunctor value to transform.")]
667		#[document_returns("The transformed profunctor value.")]
668		#[document_examples]
669		///
670		/// ```
671		/// use fp_library::{
672		/// 	brands::{
673		/// 		optics::*,
674		/// 		*,
675		/// 	},
676		/// 	classes::optics::*,
677		/// 	functions::*,
678		/// 	types::optics::*,
679		/// };
680		///
681		/// let iso: Iso<RcBrand, (i32,), (i32,), i32, i32> = Iso::new(|(x,)| x, |x| (x,));
682		/// let f = Tagged::new(42);
683		/// let reviewed = ReviewOptic::evaluate(&iso, f);
684		/// assert_eq!(reviewed.0, (42,));
685		/// ```
686		fn evaluate(
687			&self,
688			pab: Apply!(<TaggedBrand as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, B>),
689		) -> Apply!(<TaggedBrand as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, T>) {
690			let to = self.to.clone();
691			Tagged::new(to(pab.0))
692		}
693	}
694
695	/// A concrete isomorphism type where types do not change.
696	/// This matches PureScript's `Iso' s a`.
697	///
698	/// Uses [`FnBrand`](crate::brands::FnBrand) to support capturing closures.
699	#[document_type_parameters(
700		"The lifetime of the values.",
701		"The reference-counted pointer type.",
702		"The type of the structure.",
703		"The type of the focus."
704	)]
705	pub struct IsoPrime<'a, PointerBrand, S, A>
706	where
707		PointerBrand: UnsizedCoercible,
708		S: 'a,
709		A: 'a, {
710		pub(crate) from_fn: Apply!(<FnBrand<PointerBrand> as Kind!( type Of<'b, U: 'b, V: 'b>: 'b; )>::Of<'a, S, A>),
711		pub(crate) to_fn: Apply!(<FnBrand<PointerBrand> as Kind!( type Of<'b, U: 'b, V: 'b>: 'b; )>::Of<'a, A, S>),
712	}
713
714	#[document_type_parameters(
715		"The lifetime of the values.",
716		"The reference-counted pointer type.",
717		"The type of the structure.",
718		"The type of the focus."
719	)]
720	#[document_parameters("The iso instance.")]
721	impl<'a, PointerBrand, S, A> Clone for IsoPrime<'a, PointerBrand, S, A>
722	where
723		PointerBrand: UnsizedCoercible,
724		S: 'a,
725		A: 'a,
726	{
727		#[document_signature]
728		#[document_returns("A new `IsoPrime` instance that is a copy of the original.")]
729		#[document_examples]
730		///
731		/// ```
732		/// use fp_library::{
733		/// 	brands::RcBrand,
734		/// 	types::optics::IsoPrime,
735		/// };
736		///
737		/// let iso: IsoPrime<RcBrand, (i32,), i32> = IsoPrime::new(|(x,)| x, |x| (x,));
738		/// let cloned = iso.clone();
739		/// assert_eq!(cloned.from((42,)), 42);
740		/// ```
741		fn clone(&self) -> Self {
742			IsoPrime {
743				from_fn: self.from_fn.clone(),
744				to_fn: self.to_fn.clone(),
745			}
746		}
747	}
748
749	#[document_type_parameters(
750		"The lifetime of the values.",
751		"The reference-counted pointer type.",
752		"The type of the structure.",
753		"The type of the focus."
754	)]
755	#[document_parameters("The monomorphic iso instance.")]
756	impl<'a, PointerBrand, S: 'a, A: 'a> IsoPrime<'a, PointerBrand, S, A>
757	where
758		PointerBrand: UnsizedCoercible,
759	{
760		/// Create a new monomorphic isomorphism from bidirectional conversion functions.
761		#[document_signature]
762		///
763		#[document_parameters(
764			"The forward conversion function.",
765			"The backward conversion function."
766		)]
767		///
768		#[document_returns("A new instance of the type.")]
769		#[document_examples]
770		///
771		/// ```
772		/// use fp_library::{
773		/// 	brands::RcBrand,
774		/// 	types::optics::IsoPrime,
775		/// };
776		///
777		/// // Iso between a newtype and its inner value
778		/// let iso: IsoPrime<RcBrand, (i32,), i32> = IsoPrime::new(|(x,)| x, |x| (x,));
779		/// assert_eq!(iso.from((10,)), 10);
780		/// ```
781		pub fn new(
782			from: impl 'a + Fn(S) -> A,
783			to: impl 'a + Fn(A) -> S,
784		) -> Self {
785			IsoPrime {
786				from_fn: <FnBrand<PointerBrand> as LiftFn>::new(from),
787				to_fn: <FnBrand<PointerBrand> as LiftFn>::new(to),
788			}
789		}
790
791		/// Apply the forward conversion.
792		#[document_signature]
793		///
794		#[document_parameters("The structure to convert.")]
795		///
796		#[document_returns("The focus value.")]
797		///
798		#[document_examples]
799		///
800		/// ```
801		/// use fp_library::{
802		/// 	brands::RcBrand,
803		/// 	types::optics::IsoPrime,
804		/// };
805		///
806		/// let iso: IsoPrime<RcBrand, (i32,), i32> = IsoPrime::new(|(x,)| x, |x| (x,));
807		/// assert_eq!(iso.from((42,)), 42);
808		/// ```
809		pub fn from(
810			&self,
811			s: S,
812		) -> A {
813			(self.from_fn)(s)
814		}
815
816		/// Apply the backward conversion.
817		#[document_signature]
818		///
819		#[document_parameters("The focus value to convert.")]
820		///
821		#[document_returns("The structure value.")]
822		///
823		#[document_examples]
824		///
825		/// ```
826		/// use fp_library::{
827		/// 	brands::RcBrand,
828		/// 	types::optics::IsoPrime,
829		/// };
830		///
831		/// let iso: IsoPrime<RcBrand, (i32,), i32> = IsoPrime::new(|(x,)| x, |x| (x,));
832		/// assert_eq!(iso.to(42), (42,));
833		/// ```
834		pub fn to(
835			&self,
836			a: A,
837		) -> S {
838			(self.to_fn)(a)
839		}
840
841		/// Reverse the isomorphism.
842		#[document_signature]
843		///
844		#[document_returns(
845			"A new `IsoPrime` instance with the forward and backward conversions swapped."
846		)]
847		///
848		#[document_examples]
849		///
850		/// ```
851		/// use fp_library::{
852		/// 	brands::RcBrand,
853		/// 	types::optics::IsoPrime,
854		/// };
855		///
856		/// let iso: IsoPrime<RcBrand, (i32,), i32> = IsoPrime::new(|(x,)| x, |x| (x,));
857		/// let reversed = iso.reversed();
858		/// assert_eq!(reversed.from(42), (42,));
859		/// assert_eq!(reversed.to((42,)), 42);
860		/// ```
861		pub fn reversed(&self) -> IsoPrime<'a, PointerBrand, A, S> {
862			IsoPrime {
863				from_fn: self.to_fn.clone(),
864				to_fn: self.from_fn.clone(),
865			}
866		}
867	}
868
869	// Optic implementation for IsoPrime<PointerBrand, S, A>
870	#[document_type_parameters(
871		"The lifetime of the values.",
872		"The profunctor type.",
873		"The reference-counted pointer type.",
874		"The type of the structure.",
875		"The type of the focus."
876	)]
877	#[document_parameters("The monomorphic iso instance.")]
878	impl<'a, Q, PointerBrand, S, A> Optic<'a, Q, S, S, A, A> for IsoPrime<'a, PointerBrand, S, A>
879	where
880		Q: Profunctor,
881		PointerBrand: UnsizedCoercible,
882		S: 'a,
883		A: 'a,
884	{
885		#[document_signature]
886		#[document_parameters("The profunctor value to transform.")]
887		#[document_returns("The transformed profunctor value.")]
888		#[document_examples]
889		///
890		/// ```
891		/// use fp_library::{
892		/// 	brands::{
893		/// 		optics::*,
894		/// 		*,
895		/// 	},
896		/// 	classes::optics::*,
897		/// 	functions::*,
898		/// 	types::optics::*,
899		/// };
900		///
901		/// let iso: IsoPrime<RcBrand, (i32,), i32> = IsoPrime::new(|(x,)| x, |x| (x,));
902		/// let f = lift_fn_new::<RcFnBrand, _, _>(|x: i32| x + 1);
903		/// let modifier = Optic::<RcFnBrand, _, _, _, _>::evaluate(&iso, f);
904		/// assert_eq!(modifier((41,)), (42,));
905		/// ```
906		fn evaluate(
907			&self,
908			pab: Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, A>),
909		) -> Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, S>) {
910			let from_fn = self.from_fn.clone();
911			let to_fn = self.to_fn.clone();
912
913			// The Profunctor encoding of an Iso is:
914			// iso from to = dimap from to
915			Q::dimap(move |s| from_fn(s), move |a| to_fn(a), pab)
916		}
917	}
918
919	#[document_type_parameters(
920		"The lifetime of the values.",
921		"The reference-counted pointer type.",
922		"The type of the structure.",
923		"The type of the focus."
924	)]
925	#[document_parameters("The monomorphic iso instance.")]
926	impl<'a, PointerBrand, S: 'a, A: 'a> AffineTraversalOptic<'a, S, S, A, A>
927		for IsoPrime<'a, PointerBrand, S, A>
928	where
929		PointerBrand: UnsizedCoercible,
930	{
931		#[document_signature]
932		#[document_type_parameters("The profunctor type.")]
933		#[document_parameters("The profunctor value to transform.")]
934		#[document_returns("The transformed profunctor value.")]
935		#[document_examples]
936		///
937		/// ```
938		/// use fp_library::{
939		/// 	brands::{
940		/// 		optics::*,
941		/// 		*,
942		/// 	},
943		/// 	classes::optics::*,
944		/// 	functions::*,
945		/// 	types::optics::*,
946		/// };
947		///
948		/// let iso: IsoPrime<RcBrand, (i32,), i32> = IsoPrime::new(|(x,)| x, |x| (x,));
949		/// let f = lift_fn_new::<RcFnBrand, _, _>(|x: i32| x + 1);
950		/// let modifier: std::rc::Rc<dyn Fn((i32,)) -> (i32,)> =
951		/// 	AffineTraversalOptic::evaluate::<RcFnBrand>(&iso, f);
952		/// assert_eq!(modifier((41,)), (42,));
953		/// ```
954		fn evaluate<Q: Strong + Choice>(
955			&self,
956			pab: Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, A>),
957		) -> Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, S>) {
958			Optic::<Q, S, S, A, A>::evaluate(self, pab)
959		}
960	}
961
962	#[document_type_parameters(
963		"The lifetime of the values.",
964		"The cloneable function brand used by the profunctor's `Closed` instance.",
965		"The reference-counted pointer type.",
966		"The type of the structure.",
967		"The type of the focus."
968	)]
969	#[document_parameters("The monomorphic iso instance.")]
970	impl<'a, FunctionBrand: LiftFn, PointerBrand, S: 'a, A: 'a>
971		GrateOptic<'a, FunctionBrand, S, S, A, A> for IsoPrime<'a, PointerBrand, S, A>
972	where
973		PointerBrand: UnsizedCoercible,
974	{
975		#[document_signature]
976		#[document_type_parameters("The profunctor type.")]
977		#[document_parameters("The profunctor value to transform.")]
978		#[document_returns("The transformed profunctor value.")]
979		#[document_examples]
980		///
981		/// ```
982		/// use fp_library::{
983		/// 	brands::{
984		/// 		optics::*,
985		/// 		*,
986		/// 	},
987		/// 	classes::optics::*,
988		/// 	functions::*,
989		/// 	types::optics::*,
990		/// };
991		///
992		/// let iso: IsoPrime<RcBrand, (i32,), i32> = IsoPrime::new(|(x,)| x, |x| (x,));
993		/// let f = lift_fn_new::<RcFnBrand, _, _>(|x: i32| x + 1);
994		/// let modifier: std::rc::Rc<dyn Fn((i32,)) -> (i32,)> =
995		/// 	GrateOptic::<RcFnBrand, _, _, _, _>::evaluate::<RcFnBrand>(&iso, f);
996		/// assert_eq!(modifier((41,)), (42,));
997		/// ```
998		fn evaluate<Q: Closed<FunctionBrand>>(
999			&self,
1000			pab: Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, A>),
1001		) -> Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, S>) {
1002			Optic::<Q, S, S, A, A>::evaluate(self, pab)
1003		}
1004	}
1005
1006	#[document_type_parameters(
1007		"The lifetime of the values.",
1008		"The reference-counted pointer type.",
1009		"The type of the structure.",
1010		"The type of the focus."
1011	)]
1012	#[document_parameters("The monomorphic iso instance.")]
1013	impl<'a, PointerBrand, S: 'a, A: 'a> LensOptic<'a, S, S, A, A> for IsoPrime<'a, PointerBrand, S, A>
1014	where
1015		PointerBrand: UnsizedCoercible,
1016	{
1017		#[document_signature]
1018		#[document_type_parameters("The profunctor type.")]
1019		#[document_parameters("The profunctor value to transform.")]
1020		#[document_returns("The transformed profunctor value.")]
1021		#[document_examples]
1022		///
1023		/// ```
1024		/// use fp_library::{
1025		/// 	brands::{
1026		/// 		optics::*,
1027		/// 		*,
1028		/// 	},
1029		/// 	classes::optics::*,
1030		/// 	functions::*,
1031		/// 	types::optics::*,
1032		/// };
1033		///
1034		/// let iso: IsoPrime<RcBrand, (i32,), i32> = IsoPrime::new(|(x,)| x, |x| (x,));
1035		/// let f = lift_fn_new::<RcFnBrand, _, _>(|x: i32| x + 1);
1036		/// let modifier: std::rc::Rc<dyn Fn((i32,)) -> (i32,)> = LensOptic::evaluate::<RcFnBrand>(&iso, f);
1037		/// assert_eq!(modifier((41,)), (42,));
1038		/// ```
1039		fn evaluate<Q: Strong>(
1040			&self,
1041			pab: Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, A>),
1042		) -> Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, S>) {
1043			Optic::<Q, S, S, A, A>::evaluate(self, pab)
1044		}
1045	}
1046
1047	#[document_type_parameters(
1048		"The lifetime of the values.",
1049		"The reference-counted pointer type.",
1050		"The type of the structure.",
1051		"The type of the focus."
1052	)]
1053	#[document_parameters("The monomorphic iso instance.")]
1054	impl<'a, PointerBrand, S: 'a, A: 'a> PrismOptic<'a, S, S, A, A> for IsoPrime<'a, PointerBrand, S, A>
1055	where
1056		PointerBrand: UnsizedCoercible,
1057	{
1058		#[document_signature]
1059		#[document_type_parameters("The profunctor type.")]
1060		#[document_parameters("The profunctor value to transform.")]
1061		#[document_returns("The transformed profunctor value.")]
1062		#[document_examples]
1063		///
1064		/// ```
1065		/// use fp_library::{
1066		/// 	brands::{
1067		/// 		optics::*,
1068		/// 		*,
1069		/// 	},
1070		/// 	classes::optics::*,
1071		/// 	functions::*,
1072		/// 	types::optics::*,
1073		/// };
1074		///
1075		/// let iso: IsoPrime<RcBrand, (i32,), i32> = IsoPrime::new(|(x,)| x, |x| (x,));
1076		/// let f = lift_fn_new::<RcFnBrand, _, _>(|x: i32| x + 1);
1077		/// let modifier: std::rc::Rc<dyn Fn((i32,)) -> (i32,)> =
1078		/// 	PrismOptic::evaluate::<RcFnBrand>(&iso, f);
1079		/// assert_eq!(modifier((41,)), (42,));
1080		/// ```
1081		fn evaluate<Q: Choice>(
1082			&self,
1083			pab: Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, A>),
1084		) -> Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, S>) {
1085			Optic::<Q, S, S, A, A>::evaluate(self, pab)
1086		}
1087	}
1088
1089	#[document_type_parameters(
1090		"The lifetime of the values.",
1091		"The reference-counted pointer type.",
1092		"The type of the structure.",
1093		"The type of the focus."
1094	)]
1095	#[document_parameters("The monomorphic iso instance.")]
1096	impl<'a, PointerBrand, S: 'a, A: 'a> TraversalOptic<'a, S, S, A, A>
1097		for IsoPrime<'a, PointerBrand, S, A>
1098	where
1099		PointerBrand: UnsizedCoercible,
1100	{
1101		#[document_signature]
1102		#[document_type_parameters("The profunctor type.")]
1103		#[document_parameters("The profunctor value to transform.")]
1104		#[document_returns("The transformed profunctor value.")]
1105		#[document_examples]
1106		///
1107		/// ```
1108		/// use fp_library::{
1109		/// 	brands::{
1110		/// 		optics::*,
1111		/// 		*,
1112		/// 	},
1113		/// 	classes::optics::*,
1114		/// 	functions::*,
1115		/// 	types::optics::*,
1116		/// };
1117		///
1118		/// let iso: IsoPrime<RcBrand, (i32,), i32> = IsoPrime::new(|(x,)| x, |x| (x,));
1119		/// let f = lift_fn_new::<RcFnBrand, _, _>(|x: i32| x + 1);
1120		/// let modifier: std::rc::Rc<dyn Fn((i32,)) -> (i32,)> =
1121		/// 	TraversalOptic::evaluate::<RcFnBrand>(&iso, f);
1122		/// assert_eq!(modifier((41,)), (42,));
1123		/// ```
1124		fn evaluate<Q: Wander>(
1125			&self,
1126			pab: Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, A>),
1127		) -> Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, S>) {
1128			Optic::<Q, S, S, A, A>::evaluate(self, pab)
1129		}
1130	}
1131
1132	#[document_type_parameters(
1133		"The lifetime of the values.",
1134		"The reference-counted pointer type.",
1135		"The type of the structure.",
1136		"The type of the focus."
1137	)]
1138	#[document_parameters("The monomorphic iso instance.")]
1139	impl<'a, PointerBrand, S: 'a, A: 'a> GetterOptic<'a, S, A> for IsoPrime<'a, PointerBrand, S, A>
1140	where
1141		PointerBrand: UnsizedCoercible,
1142	{
1143		#[document_signature]
1144		#[document_type_parameters(
1145			"The return type of the forget profunctor.",
1146			"The reference-counted pointer type."
1147		)]
1148		#[document_parameters("The profunctor value to transform.")]
1149		#[document_returns("The transformed profunctor value.")]
1150		#[document_examples]
1151		///
1152		/// ```
1153		/// use fp_library::{
1154		/// 	brands::{
1155		/// 		optics::*,
1156		/// 		*,
1157		/// 	},
1158		/// 	classes::optics::*,
1159		/// 	functions::*,
1160		/// 	types::optics::*,
1161		/// };
1162		///
1163		/// let iso: IsoPrime<RcBrand, (i32,), i32> = IsoPrime::new(|(x,)| x, |x| (x,));
1164		/// let f = Forget::<RcBrand, i32, i32, i32>::new(|x| x);
1165		/// let folded = GetterOptic::evaluate(&iso, f);
1166		/// assert_eq!(folded.run((42,)), 42);
1167		/// ```
1168		fn evaluate<R: 'a + 'static, Q: UnsizedCoercible + 'static>(
1169			&self,
1170			pab: Apply!(<ForgetBrand<Q, R> as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, A>),
1171		) -> Apply!(<ForgetBrand<Q, R> as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, S>)
1172		{
1173			IsoOptic::evaluate::<ForgetBrand<Q, R>>(self, pab)
1174		}
1175	}
1176
1177	#[document_type_parameters(
1178		"The lifetime of the values.",
1179		"The reference-counted pointer type.",
1180		"The type of the structure.",
1181		"The type of the focus."
1182	)]
1183	#[document_parameters("The monomorphic iso instance.")]
1184	impl<'a, PointerBrand, S: 'a, A: 'a> FoldOptic<'a, S, A> for IsoPrime<'a, PointerBrand, S, A>
1185	where
1186		PointerBrand: UnsizedCoercible,
1187	{
1188		#[document_signature]
1189		#[document_type_parameters("The monoid type.", "The reference-counted pointer type.")]
1190		#[document_parameters("The profunctor value to transform.")]
1191		#[document_returns("The transformed profunctor value.")]
1192		#[document_examples]
1193		///
1194		/// ```
1195		/// use fp_library::{
1196		/// 	brands::{
1197		/// 		optics::*,
1198		/// 		*,
1199		/// 	},
1200		/// 	classes::optics::*,
1201		/// 	functions::*,
1202		/// 	types::optics::*,
1203		/// };
1204		///
1205		/// let iso: IsoPrime<RcBrand, (i32,), i32> = IsoPrime::new(|(x,)| x, |x| (x,));
1206		/// let f = Forget::<RcBrand, String, i32, i32>::new(|x| x.to_string());
1207		/// let folded = FoldOptic::evaluate(&iso, f);
1208		/// assert_eq!(folded.run((42,)), "42".to_string());
1209		/// ```
1210		fn evaluate<R: 'a + Monoid + 'static, Q: UnsizedCoercible + 'static>(
1211			&self,
1212			pab: Apply!(<ForgetBrand<Q, R> as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, A>),
1213		) -> Apply!(<ForgetBrand<Q, R> as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, S>)
1214		{
1215			IsoOptic::evaluate::<ForgetBrand<Q, R>>(self, pab)
1216		}
1217	}
1218
1219	#[document_type_parameters(
1220		"The lifetime of the values.",
1221		"The reference-counted pointer type for the setter brand.",
1222		"The reference-counted pointer type for the iso.",
1223		"The type of the structure.",
1224		"The type of the focus."
1225	)]
1226	#[document_parameters("The monomorphic iso instance.")]
1227	impl<'a, Q, PointerBrand, S: 'a, A: 'a> SetterOptic<'a, Q, S, S, A, A>
1228		for IsoPrime<'a, PointerBrand, S, A>
1229	where
1230		PointerBrand: UnsizedCoercible,
1231		Q: UnsizedCoercible,
1232	{
1233		#[document_signature]
1234		#[document_parameters("The profunctor value to transform.")]
1235		#[document_returns("The transformed profunctor value.")]
1236		#[document_examples]
1237		///
1238		/// ```
1239		/// use fp_library::{
1240		/// 	brands::{
1241		/// 		optics::*,
1242		/// 		*,
1243		/// 	},
1244		/// 	classes::optics::*,
1245		/// 	functions::*,
1246		/// 	types::optics::*,
1247		/// };
1248		///
1249		/// let iso: IsoPrime<RcBrand, (i32,), i32> = IsoPrime::new(|(x,)| x, |x| (x,));
1250		/// let f = lift_fn_new::<RcFnBrand, _, _>(|x: i32| x + 1);
1251		/// let modifier: std::rc::Rc<dyn Fn((i32,)) -> (i32,)> =
1252		/// 	SetterOptic::<RcBrand, _, _, _, _>::evaluate(&iso, f);
1253		/// assert_eq!(modifier((41,)), (42,));
1254		/// ```
1255		fn evaluate(
1256			&self,
1257			pab: Apply!(<FnBrand<Q> as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, A>),
1258		) -> Apply!(<FnBrand<Q> as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, S>) {
1259			IsoOptic::evaluate::<FnBrand<Q>>(self, pab)
1260		}
1261	}
1262
1263	#[document_type_parameters(
1264		"The lifetime of the values.",
1265		"The reference-counted pointer type.",
1266		"The type of the structure.",
1267		"The type of the focus."
1268	)]
1269	#[document_parameters("The monomorphic iso instance.")]
1270	impl<'a, PointerBrand, S: 'a, A: 'a> ReviewOptic<'a, S, S, A, A>
1271		for IsoPrime<'a, PointerBrand, S, A>
1272	where
1273		PointerBrand: UnsizedCoercible,
1274	{
1275		#[document_signature]
1276		#[document_parameters("The profunctor value to transform.")]
1277		#[document_returns("The transformed profunctor value.")]
1278		#[document_examples]
1279		///
1280		/// ```
1281		/// use fp_library::{
1282		/// 	brands::{
1283		/// 		optics::*,
1284		/// 		*,
1285		/// 	},
1286		/// 	classes::optics::*,
1287		/// 	functions::*,
1288		/// 	types::optics::*,
1289		/// };
1290		///
1291		/// let iso: IsoPrime<RcBrand, (i32,), i32> = IsoPrime::new(|(x,)| x, |x| (x,));
1292		/// let f = Tagged::new(42);
1293		/// let reviewed = ReviewOptic::evaluate(&iso, f);
1294		/// assert_eq!(reviewed.0, (42,));
1295		/// ```
1296		fn evaluate(
1297			&self,
1298			pab: Apply!(<TaggedBrand as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, A>),
1299		) -> Apply!(<TaggedBrand as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, S>) {
1300			let to_fn = self.to_fn.clone();
1301			Tagged::new(to_fn(pab.0))
1302		}
1303	}
1304
1305	#[document_type_parameters(
1306		"The lifetime of the values.",
1307		"The reference-counted pointer type.",
1308		"The type of the structure.",
1309		"The type of the focus."
1310	)]
1311	#[document_parameters("The monomorphic iso instance.")]
1312	impl<'a, PointerBrand, S: 'a, A: 'a> IsoOptic<'a, S, S, A, A> for IsoPrime<'a, PointerBrand, S, A>
1313	where
1314		PointerBrand: UnsizedCoercible,
1315	{
1316		#[document_signature]
1317		#[document_type_parameters("The profunctor type.")]
1318		#[document_parameters("The profunctor value to transform.")]
1319		#[document_returns("The transformed profunctor value.")]
1320		#[document_examples]
1321		///
1322		/// ```
1323		/// use fp_library::{
1324		/// 	brands::{
1325		/// 		optics::*,
1326		/// 		*,
1327		/// 	},
1328		/// 	classes::optics::*,
1329		/// 	functions::*,
1330		/// 	types::optics::*,
1331		/// };
1332		///
1333		/// let iso: IsoPrime<RcBrand, (i32,), i32> = IsoPrime::new(|(x,)| x, |x| (x,));
1334		/// let f = lift_fn_new::<RcFnBrand, _, _>(|x: i32| x + 1);
1335		/// let modifier: std::rc::Rc<dyn Fn((i32,)) -> (i32,)> = IsoOptic::evaluate::<RcFnBrand>(&iso, f);
1336		/// assert_eq!(modifier((41,)), (42,));
1337		/// ```
1338		fn evaluate<Q: Profunctor + 'static>(
1339			&self,
1340			pab: Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, A>),
1341		) -> Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, S>) {
1342			Optic::<Q, S, S, A, A>::evaluate(self, pab)
1343		}
1344	}
1345}
1346pub use inner::*;