Skip to main content

fp_library/types/optics/
prism.rs

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