Skip to main content

fp_library/types/optics/
grate.rs

1//! Grate optics for operating on structures through exponentiation.
2//!
3//! A grate represents a way to operate on a structure by providing a way
4//! to construct it from values extracted from functions.
5
6#[fp_macros::document_module]
7mod inner {
8	use {
9		crate::{
10			Apply,
11			brands::FnBrand,
12			classes::{
13				optics::*,
14				profunctor::Closed,
15				*,
16			},
17			kinds::*,
18			types::optics::zip_with_of,
19		},
20		fp_macros::*,
21	};
22
23	/// A polymorphic grate.
24	///
25	/// Matches PureScript's `Grate s t a b`.
26	#[document_type_parameters(
27		"The lifetime of the values.",
28		"The reference-counted pointer type.",
29		"The source type of the structure.",
30		"The target type of the structure after an update.",
31		"The source type of the focus.",
32		"The target type of the focus after an update."
33	)]
34	pub struct Grate<'a, PointerBrand, S, T, A, B>
35	where
36		PointerBrand: ToDynCloneFn,
37		S: 'a,
38		T: 'a,
39		A: 'a,
40		B: 'a, {
41		/// Grating function.
42		pub grate: <FnBrand<PointerBrand> as CloneFn>::Of<
43			'a,
44			<FnBrand<PointerBrand> as CloneFn>::Of<
45				'a,
46				<FnBrand<PointerBrand> as CloneFn>::Of<
47					'a,
48					<PointerBrand as RefCountedPointer>::Of<'a, S>,
49					A,
50				>,
51				B,
52			>,
53			T,
54		>,
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 grate instance.")]
66	impl<'a, PointerBrand, S, T, A, B> Clone for Grate<'a, PointerBrand, S, T, A, B>
67	where
68		PointerBrand: ToDynCloneFn,
69		S: 'a,
70		T: 'a,
71		A: 'a,
72		B: 'a,
73	{
74		#[document_signature]
75		#[document_returns("A new `Grate` instance that is a copy of the original.")]
76		#[document_examples]
77		///
78		/// ```
79		/// use {
80		/// 	fp_library::{
81		/// 		brands::*,
82		/// 		classes::*,
83		/// 		types::optics::Grate,
84		/// 	},
85		/// 	std::rc::Rc,
86		/// };
87		///
88		/// let grate = Grate::<'_, RcBrand, (i32, i32), (i32, i32), i32, i32>::new(|f| {
89		/// 	let get_x = <RcFnBrand as LiftFn>::new(|s: Rc<(i32, i32)>| s.0);
90		/// 	let get_y = <RcFnBrand as LiftFn>::new(|s: Rc<(i32, i32)>| s.1);
91		/// 	(f(get_x), f(get_y))
92		/// });
93		/// let cloned = grate.clone();
94		/// assert_eq!(cloned.zip_with(|(a, b)| a + b, (1, 2), (3, 4)), (4, 6));
95		/// ```
96		fn clone(&self) -> Self {
97			Grate {
98				grate: self.grate.clone(),
99			}
100		}
101	}
102
103	#[document_type_parameters(
104		"The lifetime of the values.",
105		"The reference-counted pointer type.",
106		"The source type of the structure.",
107		"The target type of the structure after an update.",
108		"The source type of the focus.",
109		"The target type of the focus after an update."
110	)]
111	#[document_parameters("The grate instance.")]
112	impl<'a, PointerBrand, S, T, A, B> Grate<'a, PointerBrand, S, T, A, B>
113	where
114		PointerBrand: ToDynCloneFn,
115		S: 'a,
116		T: 'a,
117		A: 'a,
118		B: 'a + Clone,
119	{
120		/// Creates a new `Grate` instance.
121		#[document_signature]
122		///
123		#[document_parameters("The grating function.")]
124		///
125		#[document_returns("A new instance of the type.")]
126		///
127		#[document_examples]
128		///
129		/// ```
130		/// use {
131		/// 	fp_library::{
132		/// 		brands::*,
133		/// 		classes::*,
134		/// 		types::optics::Grate,
135		/// 	},
136		/// 	std::rc::Rc,
137		/// };
138		///
139		/// let grate = Grate::<'_, RcBrand, (i32, i32), (i32, i32), i32, i32>::new(|f| {
140		/// 	let get_x = <RcFnBrand as LiftFn>::new(|s: Rc<(i32, i32)>| s.0);
141		/// 	let get_y = <RcFnBrand as LiftFn>::new(|s: Rc<(i32, i32)>| s.1);
142		/// 	(f(get_x), f(get_y))
143		/// });
144		/// assert_eq!(grate.zip_with(|(a, b)| a + b, (1, 2), (3, 4)), (4, 6));
145		/// ```
146		pub fn new(
147			grate: impl Fn(
148				<FnBrand<PointerBrand> as CloneFn>::Of<
149					'a,
150					<FnBrand<PointerBrand> as CloneFn>::Of<
151						'a,
152						<PointerBrand as RefCountedPointer>::Of<'a, S>,
153						A,
154					>,
155					B,
156				>,
157			) -> T
158			+ 'a
159		) -> Self
160		where
161			<PointerBrand as RefCountedPointer>::Of<'a, S>: Sized, {
162			Grate {
163				grate: <FnBrand<PointerBrand> as LiftFn>::new(grate),
164			}
165		}
166
167		/// Zip two structures together using this grate and a combining function.
168		///
169		/// Convenience method wrapping [`zip_with_of`].
170		#[document_signature]
171		///
172		#[document_parameters(
173			"The combining function, taking a pair `(A, A)` and returning `B`.",
174			"The first structure.",
175			"The second structure."
176		)]
177		///
178		#[document_returns("The combined structure.")]
179		#[document_examples]
180		///
181		/// ```
182		/// use {
183		/// 	fp_library::{
184		/// 		brands::*,
185		/// 		classes::*,
186		/// 		types::optics::Grate,
187		/// 	},
188		/// 	std::rc::Rc,
189		/// };
190		///
191		/// let grate = Grate::<'_, RcBrand, (i32, i32), (i32, i32), i32, i32>::new(|f| {
192		/// 	let get_x = <RcFnBrand as LiftFn>::new(|s: Rc<(i32, i32)>| s.0);
193		/// 	let get_y = <RcFnBrand as LiftFn>::new(|s: Rc<(i32, i32)>| s.1);
194		/// 	(f(get_x), f(get_y))
195		/// });
196		/// let result = grate.zip_with(|(a, b)| a + b, (1, 2), (10, 20));
197		/// assert_eq!(result, (11, 22));
198		/// ```
199		pub fn zip_with(
200			&self,
201			f: impl Fn((A, A)) -> B + 'a,
202			s1: S,
203			s2: S,
204		) -> T
205		where
206			<PointerBrand as RefCountedPointer>::Of<'a, S>: Sized, {
207			zip_with_of::<FnBrand<PointerBrand>, S, T, A, B>(self, f, s1, s2)
208		}
209	}
210
211	#[document_type_parameters(
212		"The lifetime of the values.",
213		"The profunctor type.",
214		"The reference-counted pointer type.",
215		"The source type of the structure.",
216		"The target type of the structure after an update.",
217		"The source type of the focus.",
218		"The target type of the focus after an update."
219	)]
220	#[document_parameters("The grate instance.")]
221	impl<'a, Q, PointerBrand, S, T, A, B> Optic<'a, Q, S, T, A, B>
222		for Grate<'a, PointerBrand, S, T, A, B>
223	where
224		Q: Closed<FnBrand<PointerBrand>>,
225		PointerBrand: ToDynCloneFn,
226		S: 'a,
227		T: 'a,
228		A: 'a,
229		B: 'a + Clone,
230		<PointerBrand as RefCountedPointer>::Of<'a, S>: Sized,
231	{
232		/// Evaluates the grate with a profunctor.
233		#[document_signature]
234		///
235		#[document_parameters("The profunctor value to transform.")]
236		///
237		#[document_returns("The transformed profunctor value.")]
238		///
239		#[document_examples]
240		///
241		/// ```
242		/// use {
243		/// 	fp_library::{
244		/// 		brands::*,
245		/// 		classes::{
246		/// 			optics::*,
247		/// 			*,
248		/// 		},
249		/// 		types::optics::Grate,
250		/// 	},
251		/// 	std::rc::Rc,
252		/// };
253		///
254		/// let grate = Grate::<'_, RcBrand, (i32, i32), (i32, i32), i32, i32>::new(
255		/// 	|f: Rc<dyn Fn(Rc<dyn Fn(Rc<(i32, i32)>) -> i32>) -> i32>| {
256		/// 		let get_x = <RcFnBrand as LiftFn>::new(|s: Rc<(i32, i32)>| s.0);
257		/// 		let get_y = <RcFnBrand as LiftFn>::new(|s: Rc<(i32, i32)>| s.1);
258		/// 		(f(get_x), f(get_y))
259		/// 	},
260		/// );
261		/// let f = Rc::new(|x: i32| x + 1) as Rc<dyn Fn(i32) -> i32>;
262		/// let g = Optic::<RcFnBrand, _, _, _, _>::evaluate(&grate, f);
263		/// assert_eq!(g((10, 20)), (11, 21));
264		/// ```
265		fn evaluate(
266			&self,
267			pab: Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, B>),
268		) -> Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, T>) {
269			let grate = self.grate.clone();
270
271			Q::dimap(
272				move |s: S| {
273					let s_ptr = <PointerBrand as RefCountedPointer>::new(s);
274					<FnBrand<PointerBrand> as LiftFn>::new(
275						move |f: <FnBrand<PointerBrand> as CloneFn>::Of<
276							'a,
277							<PointerBrand as RefCountedPointer>::Of<'a, S>,
278							A,
279						>|
280						      -> A { (f)(Clone::clone(&s_ptr)) },
281					)
282				},
283				move |f: <FnBrand<PointerBrand> as CloneFn>::Of<
284					'a,
285					<FnBrand<PointerBrand> as CloneFn>::Of<
286						'a,
287						<PointerBrand as RefCountedPointer>::Of<'a, S>,
288						A,
289					>,
290					B,
291				>| {
292					let f_brand = <FnBrand<PointerBrand> as LiftFn>::new(move |x| f(x));
293					grate(f_brand)
294				},
295				Q::closed(pab),
296			)
297		}
298	}
299
300	#[document_type_parameters(
301		"The lifetime of the values.",
302		"The reference-counted pointer type.",
303		"The source type of the structure.",
304		"The target type of the structure after an update.",
305		"The source type of the focus.",
306		"The target type of the focus after an update."
307	)]
308	#[document_parameters("The grate instance.")]
309	impl<'a, PointerBrand, S, T, A, B> GrateOptic<'a, FnBrand<PointerBrand>, S, T, A, B>
310		for Grate<'a, PointerBrand, S, T, A, B>
311	where
312		PointerBrand: ToDynCloneFn,
313		S: 'a,
314		A: 'a,
315		B: 'a + Clone,
316		<PointerBrand as RefCountedPointer>::Of<'a, S>: Sized,
317	{
318		#[document_signature]
319		#[document_type_parameters("The profunctor type.")]
320		#[document_parameters("The profunctor value to transform.")]
321		#[document_returns("The transformed profunctor value.")]
322		#[document_examples]
323		///
324		/// ```
325		/// use {
326		/// 	fp_library::{
327		/// 		brands::*,
328		/// 		classes::{
329		/// 			optics::*,
330		/// 			profunctor::*,
331		/// 			*,
332		/// 		},
333		/// 		types::optics::Grate,
334		/// 	},
335		/// 	std::rc::Rc,
336		/// };
337		///
338		/// let grate = Grate::<'_, RcBrand, (i32, i32), (i32, i32), i32, i32>::new(|f| {
339		/// 	(
340		/// 		f(Rc::new(|s: Rc<(i32, i32)>| s.0) as Rc<dyn Fn(Rc<(i32, i32)>) -> i32>),
341		/// 		f(Rc::new(|s: Rc<(i32, i32)>| s.1) as Rc<dyn Fn(Rc<(i32, i32)>) -> i32>),
342		/// 	)
343		/// });
344		/// let f = Rc::new(|x: i32| x + 1) as Rc<dyn Fn(i32) -> i32>;
345		/// let g = GrateOptic::<RcFnBrand, _, _, _, _>::evaluate::<RcFnBrand>(&grate, f);
346		/// assert_eq!(g((10, 20)), (11, 21));
347		/// ```
348		fn evaluate<Q: Closed<FnBrand<PointerBrand>>>(
349			&self,
350			pab: Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, B>),
351		) -> Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, T>)
352		where
353			T: 'a,
354			B: 'a, {
355			let grate = self.grate.clone();
356
357			Q::dimap(
358				move |s: S| {
359					let s_ptr = <PointerBrand as RefCountedPointer>::new(s);
360					<FnBrand<PointerBrand> as LiftFn>::new(
361						move |f: <FnBrand<PointerBrand> as CloneFn>::Of<
362							'a,
363							<PointerBrand as RefCountedPointer>::Of<'a, S>,
364							A,
365						>|
366						      -> A { (f)(Clone::clone(&s_ptr)) },
367					)
368				},
369				move |f: <FnBrand<PointerBrand> as CloneFn>::Of<
370					'a,
371					<FnBrand<PointerBrand> as CloneFn>::Of<
372						'a,
373						<PointerBrand as RefCountedPointer>::Of<'a, S>,
374						A,
375					>,
376					B,
377				>| {
378					let f_brand = <FnBrand<PointerBrand> as LiftFn>::new(move |x| f(x));
379					grate(f_brand)
380				},
381				Q::closed(pab),
382			)
383		}
384	}
385
386	#[document_type_parameters(
387		"The lifetime of the values.",
388		"The reference-counted pointer type.",
389		"The source type of the structure.",
390		"The target type of the structure after an update.",
391		"The source type of the focus.",
392		"The target type of the focus after an update."
393	)]
394	#[document_parameters("The grate instance.")]
395	impl<'a, PointerBrand, S, T, A, B> SetterOptic<'a, PointerBrand, S, T, A, B>
396		for Grate<'a, PointerBrand, S, T, A, B>
397	where
398		PointerBrand: ToDynCloneFn,
399		S: 'a,
400		A: 'a,
401		B: 'a + Clone,
402		<PointerBrand as RefCountedPointer>::Of<'a, S>: Sized,
403	{
404		#[document_signature]
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		/// 		classes::{
414		/// 			optics::*,
415		/// 			profunctor::*,
416		/// 			*,
417		/// 		},
418		/// 		types::optics::Grate,
419		/// 	},
420		/// 	std::rc::Rc,
421		/// };
422		///
423		/// let grate = Grate::<'_, RcBrand, (i32, i32), (i32, i32), i32, i32>::new(|f| {
424		/// 	(
425		/// 		f(Rc::new(|s: Rc<(i32, i32)>| s.0) as Rc<dyn Fn(Rc<(i32, i32)>) -> i32>),
426		/// 		f(Rc::new(|s: Rc<(i32, i32)>| s.1) as Rc<dyn Fn(Rc<(i32, i32)>) -> i32>),
427		/// 	)
428		/// });
429		/// let f = Rc::new(|x: i32| x + 1) as Rc<dyn Fn(i32) -> i32>;
430		/// let g: Rc<dyn Fn((i32, i32)) -> (i32, i32)> =
431		/// 	SetterOptic::<RcBrand, _, _, _, _>::evaluate(&grate, f);
432		/// assert_eq!(g((10, 20)), (11, 21));
433		/// ```
434		fn evaluate(
435			&self,
436			pab: Apply!(<FnBrand<PointerBrand> as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, B>),
437		) -> Apply!(<FnBrand<PointerBrand> as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, T>)
438		{
439			GrateOptic::<FnBrand<PointerBrand>, S, T, A, B>::evaluate::<FnBrand<PointerBrand>>(
440				self, pab,
441			)
442		}
443	}
444
445	/// A monomorphic grate.
446	///
447	/// Matches PureScript's `Grate' s a`.
448	#[document_type_parameters(
449		"The lifetime of the values.",
450		"The reference-counted pointer type.",
451		"The type of the structure.",
452		"The type of the focus."
453	)]
454	pub struct GratePrime<'a, PointerBrand, S, A>
455	where
456		PointerBrand: ToDynCloneFn,
457		S: 'a,
458		A: 'a, {
459		pub(crate) grate_fn: <FnBrand<PointerBrand> as CloneFn>::Of<
460			'a,
461			<FnBrand<PointerBrand> as CloneFn>::Of<
462				'a,
463				<FnBrand<PointerBrand> as CloneFn>::Of<
464					'a,
465					<PointerBrand as RefCountedPointer>::Of<'a, S>,
466					A,
467				>,
468				A,
469			>,
470			S,
471		>,
472	}
473
474	#[document_type_parameters(
475		"The lifetime of the values.",
476		"The reference-counted pointer type.",
477		"The type of the structure.",
478		"The type of the focus."
479	)]
480	#[document_parameters("The grate instance.")]
481	impl<'a, PointerBrand, S, A> Clone for GratePrime<'a, PointerBrand, S, A>
482	where
483		PointerBrand: ToDynCloneFn,
484		S: 'a,
485		A: 'a,
486	{
487		#[document_signature]
488		#[document_returns("The cloned grate instance.")]
489		#[document_examples]
490		///
491		/// ```
492		/// use {
493		/// 	fp_library::{
494		/// 		brands::*,
495		/// 		classes::*,
496		/// 		types::optics::GratePrime,
497		/// 	},
498		/// 	std::rc::Rc,
499		/// };
500		///
501		/// let grate = GratePrime::<'_, RcBrand, (i32, i32), i32>::new(
502		/// 	|f: Rc<dyn Fn(Rc<dyn Fn(Rc<(i32, i32)>) -> i32>) -> i32>| {
503		/// 		(
504		/// 			f(<RcFnBrand as LiftFn>::new(|s: Rc<(i32, i32)>| s.0)),
505		/// 			f(<RcFnBrand as LiftFn>::new(|s: Rc<(i32, i32)>| s.1)),
506		/// 		)
507		/// 	},
508		/// );
509		/// let cloned = grate.clone();
510		/// assert_eq!(cloned.zip_with(|(a, b)| a + b, (1, 2), (3, 4)), (4, 6));
511		/// ```
512		fn clone(&self) -> Self {
513			GratePrime {
514				grate_fn: self.grate_fn.clone(),
515			}
516		}
517	}
518
519	#[document_type_parameters(
520		"The lifetime of the values.",
521		"The reference-counted pointer type.",
522		"The type of the structure.",
523		"The type of the focus."
524	)]
525	impl<'a, PointerBrand, S, A> GratePrime<'a, PointerBrand, S, A>
526	where
527		PointerBrand: ToDynCloneFn,
528		S: 'a,
529		A: 'a,
530	{
531		/// Creates a new `GratePrime` instance.
532		#[document_signature]
533		///
534		#[document_parameters("The grating function.")]
535		///
536		#[document_returns("A new instance of the type.")]
537		///
538		#[document_examples]
539		///
540		/// ```
541		/// use {
542		/// 	fp_library::{
543		/// 		brands::*,
544		/// 		classes::*,
545		/// 		types::optics::GratePrime,
546		/// 	},
547		/// 	std::rc::Rc,
548		/// };
549		///
550		/// let grate = GratePrime::<'_, RcBrand, (i32, i32), i32>::new(
551		/// 	|f: Rc<dyn Fn(Rc<dyn Fn(Rc<(i32, i32)>) -> i32>) -> i32>| {
552		/// 		(
553		/// 			f(<RcFnBrand as LiftFn>::new(|s: Rc<(i32, i32)>| s.0)),
554		/// 			f(<RcFnBrand as LiftFn>::new(|s: Rc<(i32, i32)>| s.1)),
555		/// 		)
556		/// 	},
557		/// );
558		/// assert_eq!(grate.zip_with(|(a, b)| a + b, (1, 2), (3, 4)), (4, 6));
559		/// ```
560		pub fn new(
561			grate: impl Fn(
562				<FnBrand<PointerBrand> as CloneFn>::Of<
563					'a,
564					<FnBrand<PointerBrand> as CloneFn>::Of<
565						'a,
566						<PointerBrand as RefCountedPointer>::Of<'a, S>,
567						A,
568					>,
569					A,
570				>,
571			) -> S
572			+ 'a
573		) -> Self
574		where
575			<PointerBrand as RefCountedPointer>::Of<'a, S>: Sized, {
576			GratePrime {
577				grate_fn: <FnBrand<PointerBrand> as LiftFn>::new(grate),
578			}
579		}
580	}
581
582	#[document_type_parameters(
583		"The lifetime of the values.",
584		"The reference-counted pointer type.",
585		"The type of the structure.",
586		"The type of the focus."
587	)]
588	#[document_parameters("The grate instance.")]
589	impl<'a, PointerBrand, S, A> GratePrime<'a, PointerBrand, S, A>
590	where
591		PointerBrand: ToDynCloneFn,
592		S: 'a,
593		A: 'a + Clone,
594	{
595		/// Zip two structures together using this grate and a combining function.
596		///
597		/// Convenience method wrapping [`zip_with_of`].
598		#[document_signature]
599		///
600		#[document_parameters(
601			"The combining function, taking a pair `(A, A)` and returning `A`.",
602			"The first structure.",
603			"The second structure."
604		)]
605		///
606		#[document_returns("The combined structure.")]
607		#[document_examples]
608		///
609		/// ```
610		/// use {
611		/// 	fp_library::{
612		/// 		brands::*,
613		/// 		classes::*,
614		/// 		types::optics::GratePrime,
615		/// 	},
616		/// 	std::rc::Rc,
617		/// };
618		///
619		/// let grate = GratePrime::<'_, RcBrand, (i32, i32), i32>::new(
620		/// 	|f: Rc<dyn Fn(Rc<dyn Fn(Rc<(i32, i32)>) -> i32>) -> i32>| {
621		/// 		(
622		/// 			f(<RcFnBrand as LiftFn>::new(|s: Rc<(i32, i32)>| s.0)),
623		/// 			f(<RcFnBrand as LiftFn>::new(|s: Rc<(i32, i32)>| s.1)),
624		/// 		)
625		/// 	},
626		/// );
627		/// let result = grate.zip_with(|(a, b)| a + b, (1, 2), (10, 20));
628		/// assert_eq!(result, (11, 22));
629		/// ```
630		pub fn zip_with(
631			&self,
632			f: impl Fn((A, A)) -> A + 'a,
633			s1: S,
634			s2: S,
635		) -> S
636		where
637			<PointerBrand as RefCountedPointer>::Of<'a, S>: Sized, {
638			zip_with_of::<FnBrand<PointerBrand>, S, S, A, A>(self, f, s1, s2)
639		}
640	}
641
642	#[document_type_parameters(
643		"The lifetime of the values.",
644		"The profunctor type.",
645		"The reference-counted pointer type.",
646		"The type of the structure.",
647		"The type of the focus."
648	)]
649	#[document_parameters("The grate instance.")]
650	impl<'a, Q, PointerBrand, S, A> Optic<'a, Q, S, S, A, A> for GratePrime<'a, PointerBrand, S, A>
651	where
652		Q: Closed<FnBrand<PointerBrand>>,
653		PointerBrand: ToDynCloneFn,
654		S: 'a,
655		A: 'a + Clone,
656		<PointerBrand as RefCountedPointer>::Of<'a, S>: Sized,
657	{
658		/// Evaluates the grate with a profunctor.
659		#[document_signature]
660		#[document_parameters("The profunctor value to transform.")]
661		#[document_returns("The transformed profunctor value.")]
662		///
663		#[document_examples]
664		///
665		/// ```
666		/// use {
667		/// 	fp_library::{
668		/// 		brands::*,
669		/// 		classes::{
670		/// 			optics::*,
671		/// 			*,
672		/// 		},
673		/// 		types::optics::GratePrime,
674		/// 	},
675		/// 	std::rc::Rc,
676		/// };
677		///
678		/// let grate = GratePrime::<'_, RcBrand, (i32, i32), i32>::new(
679		/// 	|f: Rc<dyn Fn(Rc<dyn Fn(Rc<(i32, i32)>) -> i32>) -> i32>| {
680		/// 		(
681		/// 			f(<RcFnBrand as LiftFn>::new(|s: Rc<(i32, i32)>| s.0)),
682		/// 			f(<RcFnBrand as LiftFn>::new(|s: Rc<(i32, i32)>| s.1)),
683		/// 		)
684		/// 	},
685		/// );
686		/// let f = Rc::new(|x: i32| x + 1) as Rc<dyn Fn(i32) -> i32>;
687		/// let g = Optic::<RcFnBrand, _, _, _, _>::evaluate(&grate, f);
688		/// assert_eq!(g((10, 20)), (11, 21));
689		/// ```
690		fn evaluate(
691			&self,
692			pab: Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, A>),
693		) -> Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, S>) {
694			let grate = self.grate_fn.clone();
695
696			Q::dimap(
697				move |s: S| {
698					let s_ptr = <PointerBrand as RefCountedPointer>::new(s);
699					<FnBrand<PointerBrand> as LiftFn>::new(
700						move |f: <FnBrand<PointerBrand> as CloneFn>::Of<
701							'a,
702							<PointerBrand as RefCountedPointer>::Of<'a, S>,
703							A,
704						>| { (f)(Clone::clone(&s_ptr)) },
705					)
706				},
707				move |f: <FnBrand<PointerBrand> as CloneFn>::Of<
708					'a,
709					<FnBrand<PointerBrand> as CloneFn>::Of<
710						'a,
711						<PointerBrand as RefCountedPointer>::Of<'a, S>,
712						A,
713					>,
714					A,
715				>| {
716					let f_brand = <FnBrand<PointerBrand> as LiftFn>::new(move |x| f(x));
717					grate(f_brand)
718				},
719				Q::closed(pab),
720			)
721		}
722	}
723
724	#[document_type_parameters(
725		"The lifetime of the values.",
726		"The reference-counted pointer type.",
727		"The type of the structure.",
728		"The type of the focus."
729	)]
730	#[document_parameters("The grate instance.")]
731	impl<'a, PointerBrand, S, A> GrateOptic<'a, FnBrand<PointerBrand>, S, S, A, A>
732		for GratePrime<'a, PointerBrand, S, A>
733	where
734		PointerBrand: ToDynCloneFn,
735		S: 'a,
736		A: 'a + Clone,
737		<PointerBrand as RefCountedPointer>::Of<'a, S>: Sized,
738	{
739		#[document_signature]
740		#[document_type_parameters("The profunctor type.")]
741		#[document_parameters("The profunctor value to transform.")]
742		#[document_returns("The transformed profunctor value.")]
743		#[document_examples]
744		///
745		/// ```
746		/// use {
747		/// 	fp_library::{
748		/// 		brands::*,
749		/// 		classes::{
750		/// 			optics::*,
751		/// 			*,
752		/// 		},
753		/// 		types::optics::GratePrime,
754		/// 	},
755		/// 	std::rc::Rc,
756		/// };
757		///
758		/// let grate = GratePrime::<'_, RcBrand, (i32, i32), i32>::new(
759		/// 	|f: Rc<dyn Fn(Rc<dyn Fn(Rc<(i32, i32)>) -> i32>) -> i32>| {
760		/// 		(
761		/// 			f(<RcFnBrand as LiftFn>::new(|s: Rc<(i32, i32)>| s.0)),
762		/// 			f(<RcFnBrand as LiftFn>::new(|s: Rc<(i32, i32)>| s.1)),
763		/// 		)
764		/// 	},
765		/// );
766		/// let f = Rc::new(|x: i32| x + 1) as Rc<dyn Fn(i32) -> i32>;
767		/// let g = GrateOptic::<RcFnBrand, _, _, _, _>::evaluate::<RcFnBrand>(&grate, f);
768		/// assert_eq!(g((10, 20)), (11, 21));
769		/// ```
770		fn evaluate<Q: Closed<FnBrand<PointerBrand>>>(
771			&self,
772			pab: Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, A>),
773		) -> Apply!(<Q as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, S>) {
774			let grate = self.grate_fn.clone();
775
776			Q::dimap(
777				move |s: S| {
778					let s_ptr = <PointerBrand as RefCountedPointer>::new(s);
779					<FnBrand<PointerBrand> as LiftFn>::new(
780						move |f: <FnBrand<PointerBrand> as CloneFn>::Of<
781							'a,
782							<PointerBrand as RefCountedPointer>::Of<'a, S>,
783							A,
784						>| { (f)(Clone::clone(&s_ptr)) },
785					)
786				},
787				move |f: <FnBrand<PointerBrand> as CloneFn>::Of<
788					'a,
789					<FnBrand<PointerBrand> as CloneFn>::Of<
790						'a,
791						<PointerBrand as RefCountedPointer>::Of<'a, S>,
792						A,
793					>,
794					A,
795				>| {
796					let f_brand = <FnBrand<PointerBrand> as LiftFn>::new(move |x| f(x));
797					grate(f_brand)
798				},
799				Q::closed(pab),
800			)
801		}
802	}
803
804	#[document_type_parameters(
805		"The lifetime of the values.",
806		"The reference-counted pointer type.",
807		"The type of the structure.",
808		"The type of the focus."
809	)]
810	#[document_parameters("The grate instance.")]
811	impl<'a, PointerBrand, S, A> SetterOptic<'a, PointerBrand, S, S, A, A>
812		for GratePrime<'a, PointerBrand, S, A>
813	where
814		PointerBrand: ToDynCloneFn,
815		S: 'a,
816		A: 'a + Clone,
817		<PointerBrand as RefCountedPointer>::Of<'a, S>: Sized,
818	{
819		#[document_signature]
820		#[document_parameters("The profunctor value to transform.")]
821		#[document_returns("The transformed profunctor value.")]
822		#[document_examples]
823		///
824		/// ```
825		/// use {
826		/// 	fp_library::{
827		/// 		brands::*,
828		/// 		classes::{
829		/// 			optics::*,
830		/// 			profunctor::*,
831		/// 			*,
832		/// 		},
833		/// 		types::optics::GratePrime,
834		/// 	},
835		/// 	std::rc::Rc,
836		/// };
837		///
838		/// let grate = GratePrime::<'_, RcBrand, (i32, i32), i32>::new(|f| {
839		/// 	(
840		/// 		f(Rc::new(|s: Rc<(i32, i32)>| s.0) as Rc<dyn Fn(Rc<(i32, i32)>) -> i32>),
841		/// 		f(Rc::new(|s: Rc<(i32, i32)>| s.1) as Rc<dyn Fn(Rc<(i32, i32)>) -> i32>),
842		/// 	)
843		/// });
844		/// let f = Rc::new(|x: i32| x + 1) as Rc<dyn Fn(i32) -> i32>;
845		/// let g: Rc<dyn Fn((i32, i32)) -> (i32, i32)> =
846		/// 	SetterOptic::<RcBrand, _, _, _, _>::evaluate(&grate, f);
847		/// assert_eq!(g((10, 20)), (11, 21));
848		/// ```
849		fn evaluate(
850			&self,
851			pab: Apply!(<FnBrand<PointerBrand> as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, A, A>),
852		) -> Apply!(<FnBrand<PointerBrand> as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, S, S>)
853		{
854			GrateOptic::<FnBrand<PointerBrand>, S, S, A, A>::evaluate::<FnBrand<PointerBrand>>(
855				self, pab,
856			)
857		}
858	}
859}
860pub use inner::*;