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