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