Skip to main content

fp_library/types/optics/
lens.rs

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