Skip to main content

fp_library/types/optics/
bazaar.rs

1//! The `Bazaar` profunctor, used to characterize traversals.
2//!
3//! `Bazaar<A, B, S, T>` wraps a decomposition function `S -> BazaarList<A, B, T>` that extracts
4//! a list of foci from a source and provides a rebuild function.
5//!
6//! This is a Rust port of PureScript's `Data.Lens.Internal.Bazaar`, specialized to the function
7//! profunctor (`p = (->)`). The rank-2 polymorphism over applicatives is handled via the
8//! [`BazaarList`] decomposition: instead of storing `forall f. Applicative f => (a -> f b) -> s -> f t`,
9//! we store `s -> (Vec<a>, Vec<b> -> t)` and interpret it with any applicative at run time.
10
11#[fp_macros::document_module]
12mod inner {
13	use {
14		crate::{
15			Apply,
16			brands::{
17				VecBrand,
18				optics::*,
19			},
20			classes::{
21				ApplyFirst,
22				ApplySecond,
23				CloneableFn,
24				Functor,
25				Lift,
26				Pointed,
27				RefCountedPointer,
28				Semiapplicative,
29				Traversable,
30				optics::traversal::TraversalFunc,
31				profunctor::{
32					Choice,
33					Profunctor,
34					Strong,
35					Wander,
36				},
37			},
38			impl_kind,
39			kinds::*,
40		},
41		fp_macros::*,
42	};
43
44	/// Type alias to extract the pointer brand from a `CloneableFn` implementor.
45	type Ptr<FunctionBrand> = <FunctionBrand as CloneableFn>::PointerBrand;
46
47	// ── BazaarList ──────────────────────────────────────────────────────
48
49	/// A decomposed traversal structure: a list of foci paired with a rebuild function.
50	///
51	/// `BazaarList` is [`Applicative`](crate::classes::Applicative) in `T`, which is the
52	/// key property that enables [`Bazaar`] to defer the choice of applicative until
53	/// [`run_bazaar`] time.
54	#[document_type_parameters(
55		"The lifetime of the values.",
56		"The cloneable function brand.",
57		"The type of focus values extracted from the source.",
58		"The type of replacement values used during reconstruction.",
59		"The result type after reconstruction."
60	)]
61	pub struct BazaarList<'a, FunctionBrand: CloneableFn, A: 'a, B: 'a, T: 'a> {
62		/// The list of focus values extracted from the source.
63		pub foci: Vec<A>,
64		/// A function that reconstructs the target from a list of replacement values.
65		pub rebuild: <FunctionBrand as CloneableFn>::Of<'a, Vec<B>, T>,
66	}
67
68	impl_kind! {
69		impl<FunctionBrand: CloneableFn + 'static, A: 'static, B: 'static> for BazaarListBrand<FunctionBrand, A, B> {
70			type Of<'a, T: 'a>: 'a = BazaarList<'a, FunctionBrand, A, B, T>;
71		}
72	}
73
74	#[document_type_parameters(
75		"The cloneable function brand.",
76		"The focus type.",
77		"The replacement type."
78	)]
79	impl<FunctionBrand: CloneableFn + 'static, A: 'static, B: 'static> Functor
80		for BazaarListBrand<FunctionBrand, A, B>
81	{
82		/// Maps a function over the result type of a `BazaarList`.
83		#[document_signature]
84		///
85		#[document_type_parameters(
86			"The lifetime of the values.",
87			"The original result type.",
88			"The new result type."
89		)]
90		///
91		#[document_parameters("The function to apply.", "The bazaar list to map over.")]
92		///
93		#[document_returns("A new `BazaarList` with the same foci but a transformed rebuild.")]
94		///
95		#[document_examples]
96		///
97		/// ```
98		/// use fp_library::{
99		/// 	brands::{
100		/// 		optics::*,
101		/// 		*,
102		/// 	},
103		/// 	functions::*,
104		/// 	types::optics::*,
105		/// };
106		///
107		/// let bl = BazaarList::<RcFnBrand, i32, i32, i32> {
108		/// 	foci: vec![1, 2],
109		/// 	rebuild: cloneable_fn_new::<RcFnBrand, _, _>(|bs: Vec<i32>| bs.iter().sum()),
110		/// };
111		/// let mapped = map::<BazaarListBrand<RcFnBrand, i32, i32>, _, _>(|t: i32| t * 10, bl);
112		/// assert_eq!((mapped.rebuild)(vec![3, 4]), 70);
113		/// ```
114		fn map<'a, T: 'a, U: 'a>(
115			func: impl Fn(T) -> U + 'a,
116			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, T>),
117		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, U>) {
118			let rebuild = fa.rebuild;
119			BazaarList {
120				foci: fa.foci,
121				rebuild: <FunctionBrand as CloneableFn>::new(move |bs: Vec<B>| {
122					func((*rebuild)(bs))
123				}),
124			}
125		}
126	}
127
128	#[document_type_parameters(
129		"The cloneable function brand.",
130		"The focus type.",
131		"The replacement type."
132	)]
133	impl<FunctionBrand: CloneableFn + 'static, A: 'static, B: 'static> Pointed
134		for BazaarListBrand<FunctionBrand, A, B>
135	{
136		/// Wraps a value in a `BazaarList` with no foci.
137		#[document_signature]
138		///
139		#[document_type_parameters("The lifetime of the value.", "The type of the value.")]
140		///
141		#[document_parameters("The value to wrap.")]
142		///
143		#[document_returns("A `BazaarList` with empty foci that ignores its input.")]
144		///
145		#[document_examples]
146		///
147		/// ```
148		/// use fp_library::{
149		/// 	brands::{
150		/// 		optics::*,
151		/// 		*,
152		/// 	},
153		/// 	functions::*,
154		/// 	types::optics::*,
155		/// };
156		///
157		/// let bl = pure::<BazaarListBrand<RcFnBrand, i32, i32>, _>(42);
158		/// assert_eq!((bl.rebuild)(vec![]), 42);
159		/// ```
160		fn pure<'a, T: 'a>(a: T) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, T>) {
161			let a = Ptr::<FunctionBrand>::take_cell_new(a);
162			BazaarList {
163				foci: vec![],
164				rebuild: <FunctionBrand as CloneableFn>::new(move |_: Vec<B>| {
165					// SAFETY: take_cell_take is called exactly once per the optics rebuild contract
166					#[allow(clippy::expect_used)]
167					Ptr::<FunctionBrand>::take_cell_take(&a)
168						.expect("BazaarList::pure rebuild called more than once")
169				}),
170			}
171		}
172	}
173
174	#[document_type_parameters(
175		"The cloneable function brand.",
176		"The focus type.",
177		"The replacement type."
178	)]
179	impl<FunctionBrand: CloneableFn + 'static, A: 'static, B: 'static> Lift
180		for BazaarListBrand<FunctionBrand, A, B>
181	{
182		/// Lifts a binary function to combine two `BazaarList` values.
183		///
184		/// Concatenates the foci from both lists and splits the replacement vector
185		/// at the boundary when rebuilding.
186		#[document_signature]
187		///
188		#[document_type_parameters(
189			"The lifetime of the values.",
190			"The result type of the first `BazaarList`.",
191			"The result type of the second `BazaarList`.",
192			"The combined result type."
193		)]
194		///
195		#[document_parameters(
196			"The binary function to combine results.",
197			"The first `BazaarList`.",
198			"The second `BazaarList`."
199		)]
200		///
201		#[document_returns(
202			"A `BazaarList` with concatenated foci whose rebuild splits and delegates."
203		)]
204		///
205		#[document_examples]
206		///
207		/// ```
208		/// use fp_library::{
209		/// 	brands::{
210		/// 		optics::*,
211		/// 		*,
212		/// 	},
213		/// 	functions::*,
214		/// 	types::optics::*,
215		/// };
216		///
217		/// let bl1 = BazaarList::<RcFnBrand, i32, i32, i32> {
218		/// 	foci: vec![1],
219		/// 	rebuild: cloneable_fn_new::<RcFnBrand, _, _>(|bs: Vec<i32>| bs[0]),
220		/// };
221		/// let bl2 = BazaarList::<RcFnBrand, i32, i32, i32> {
222		/// 	foci: vec![2],
223		/// 	rebuild: cloneable_fn_new::<RcFnBrand, _, _>(|bs: Vec<i32>| bs[0]),
224		/// };
225		/// let combined = lift2::<BazaarListBrand<RcFnBrand, i32, i32>, _, _, _>(|a, b| a + b, bl1, bl2);
226		/// assert_eq!(combined.foci, vec![1, 2]);
227		/// assert_eq!((combined.rebuild)(vec![10, 20]), 30);
228		/// ```
229		fn lift2<'a, T, U, V>(
230			func: impl Fn(T, U) -> V + 'a,
231			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, T>),
232			fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, U>),
233		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, V>)
234		where
235			T: Clone + 'a,
236			U: Clone + 'a,
237			V: 'a, {
238			let split_at = fa.foci.len();
239			let mut foci = fa.foci;
240			foci.extend(fb.foci);
241			let rebuild_a = fa.rebuild;
242			let rebuild_b = fb.rebuild;
243			BazaarList {
244				foci,
245				rebuild: <FunctionBrand as CloneableFn>::new(move |mut bs: Vec<B>| {
246					let right = bs.split_off(split_at);
247					func((*rebuild_a)(bs), (*rebuild_b)(right))
248				}),
249			}
250		}
251	}
252
253	#[document_type_parameters(
254		"The cloneable function brand.",
255		"The focus type.",
256		"The replacement type."
257	)]
258	impl<FunctionBrand: CloneableFn + 'static, A: 'static, B: 'static> Semiapplicative
259		for BazaarListBrand<FunctionBrand, A, B>
260	{
261		/// Applies a `BazaarList` of functions to a `BazaarList` of values.
262		#[document_signature]
263		///
264		#[document_type_parameters(
265			"The lifetime of the values.",
266			"The brand of the cloneable function wrapper.",
267			"The input type.",
268			"The output type."
269		)]
270		///
271		#[document_parameters(
272			"The `BazaarList` containing the function.",
273			"The `BazaarList` containing the value."
274		)]
275		///
276		#[document_returns("A `BazaarList` with the function applied.")]
277		///
278		#[document_examples]
279		///
280		/// ```
281		/// use fp_library::{
282		/// 	brands::{
283		/// 		optics::*,
284		/// 		*,
285		/// 	},
286		/// 	functions::*,
287		/// 	types::optics::*,
288		/// };
289		///
290		/// let bl_f = BazaarList::<RcFnBrand, i32, i32, _> {
291		/// 	foci: vec![],
292		/// 	rebuild: cloneable_fn_new::<RcFnBrand, _, _>(|_: Vec<i32>| {
293		/// 		cloneable_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2)
294		/// 	}),
295		/// };
296		/// let bl_a = BazaarList::<RcFnBrand, i32, i32, i32> {
297		/// 	foci: vec![5],
298		/// 	rebuild: cloneable_fn_new::<RcFnBrand, _, _>(|bs: Vec<i32>| bs[0]),
299		/// };
300		/// let result = apply::<RcFnBrand, BazaarListBrand<RcFnBrand, i32, i32>, _, _>(bl_f, bl_a);
301		/// assert_eq!((result.rebuild)(vec![7]), 14);
302		/// ```
303		fn apply<'a, FnB: 'a + CloneableFn, T: 'a + Clone, U: 'a>(
304			ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnB as CloneableFn>::Of<'a, T, U>>),
305			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, T>),
306		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, U>) {
307			let split_at = ff.foci.len();
308			let mut foci = ff.foci;
309			foci.extend(fa.foci);
310			let rebuild_f = ff.rebuild;
311			let rebuild_a = fa.rebuild;
312			BazaarList {
313				foci,
314				rebuild: <FunctionBrand as CloneableFn>::new(move |mut bs: Vec<B>| {
315					let right = bs.split_off(split_at);
316					(*rebuild_f)(bs)((*rebuild_a)(right))
317				}),
318			}
319		}
320	}
321
322	#[document_type_parameters(
323		"The cloneable function brand.",
324		"The focus type.",
325		"The replacement type."
326	)]
327	impl<FunctionBrand: CloneableFn + 'static, A: 'static, B: 'static> ApplyFirst
328		for BazaarListBrand<FunctionBrand, A, B>
329	{
330	}
331	#[document_type_parameters(
332		"The cloneable function brand.",
333		"The focus type.",
334		"The replacement type."
335	)]
336	impl<FunctionBrand: CloneableFn + 'static, A: 'static, B: 'static> ApplySecond
337		for BazaarListBrand<FunctionBrand, A, B>
338	{
339	}
340
341	// ── Bazaar ──────────────────────────────────────────────────────────
342
343	/// The `Bazaar` profunctor, used to characterize traversals.
344	///
345	/// Wraps a decomposition function from `S` to [`BazaarList`], which extracts
346	/// all focus values and provides a rebuild function. Use [`run_bazaar`] to
347	/// interpret the `Bazaar` with any [`Applicative`](crate::classes::Applicative).
348	///
349	/// This is a port of PureScript's `Bazaar ((->) :: Type -> Type -> Type) a b s t`,
350	/// specialized to the function profunctor.
351	#[document_type_parameters(
352		"The lifetime of the values.",
353		"The cloneable function brand.",
354		"The type of focus values extracted from the source.",
355		"The type of replacement values used during reconstruction.",
356		"The source type.",
357		"The target type."
358	)]
359	pub struct Bazaar<'a, FunctionBrand: CloneableFn + 'a, A: 'a, B: 'a, S: 'a, T: 'a> {
360		/// Decomposes a source into a [`BazaarList`] of foci and a rebuild function.
361		pub run: <FunctionBrand as CloneableFn>::Of<'a, S, BazaarList<'a, FunctionBrand, A, B, T>>,
362	}
363
364	#[document_type_parameters(
365		"The lifetime of the values.",
366		"The cloneable function brand.",
367		"The type of focus values extracted from the source.",
368		"The type of replacement values used during reconstruction.",
369		"The source type.",
370		"The target type."
371	)]
372	impl<'a, FunctionBrand: CloneableFn, A: 'a, B: 'a, S: 'a, T: 'a>
373		Bazaar<'a, FunctionBrand, A, B, S, T>
374	{
375		/// Creates a new `Bazaar` instance.
376		#[document_signature]
377		///
378		#[document_parameters("The decomposition function from source to `BazaarList`.")]
379		///
380		#[document_returns("A new instance of the type.")]
381		///
382		#[document_examples]
383		///
384		/// ```
385		/// use fp_library::{
386		/// 	brands::{
387		/// 		optics::*,
388		/// 		*,
389		/// 	},
390		/// 	functions::*,
391		/// 	types::optics::*,
392		/// };
393		///
394		/// let bazaar = Bazaar::<RcFnBrand, i32, i32, i32, i32>::new(cloneable_fn_new::<RcFnBrand, _, _>(
395		/// 	|s: i32| BazaarList {
396		/// 		foci: vec![s],
397		/// 		rebuild: cloneable_fn_new::<RcFnBrand, _, _>(|bs: Vec<i32>| bs[0]),
398		/// 	},
399		/// ));
400		/// let bl = (bazaar.run)(42);
401		/// assert_eq!(bl.foci, vec![42]);
402		/// assert_eq!((bl.rebuild)(vec![100]), 100);
403		/// ```
404		pub fn new(
405			run: <FunctionBrand as CloneableFn>::Of<'a, S, BazaarList<'a, FunctionBrand, A, B, T>>
406		) -> Self {
407			Bazaar {
408				run,
409			}
410		}
411	}
412
413	/// Interprets a [`Bazaar`] with a specific [`Applicative`](crate::classes::Applicative).
414	///
415	/// Given a handler `A -> F B` and a source `S`, decomposes the source via the Bazaar,
416	/// maps each focus through the handler, sequences the results, and rebuilds the target.
417	#[document_signature]
418	///
419	#[document_type_parameters(
420		"The lifetime of the values.",
421		"The cloneable function brand.",
422		"The type of focus values.",
423		"The type of replacement values.",
424		"The source type.",
425		"The target type.",
426		"The applicative context."
427	)]
428	///
429	#[document_parameters(
430		"The handler function that lifts each focus into the applicative.",
431		"The source value.",
432		"The bazaar to interpret."
433	)]
434	///
435	#[document_returns("The target wrapped in the applicative context.")]
436	///
437	#[document_examples]
438	///
439	/// ```
440	/// use fp_library::{
441	/// 	brands::{
442	/// 		optics::*,
443	/// 		*,
444	/// 	},
445	/// 	functions::*,
446	/// 	types::optics::*,
447	/// };
448	///
449	/// let bazaar =
450	/// 	Bazaar::<RcFnBrand, i32, i32, Vec<i32>, Vec<i32>>::new(
451	/// 		cloneable_fn_new::<RcFnBrand, _, _>(|s: Vec<i32>| {
452	/// 			let len = s.len();
453	/// 			BazaarList {
454	/// 				foci: s,
455	/// 				rebuild: cloneable_fn_new::<RcFnBrand, _, _>(move |bs: Vec<i32>| {
456	/// 					bs.into_iter().take(len).collect()
457	/// 				}),
458	/// 			}
459	/// 		}),
460	/// 	);
461	/// let result = run_bazaar::<RcFnBrand, _, _, _, _, OptionBrand>(
462	/// 	|x: i32| Some(x + 1),
463	/// 	vec![1, 2, 3],
464	/// 	&bazaar,
465	/// );
466	/// assert_eq!(result, Some(vec![2, 3, 4]));
467	/// ```
468	pub fn run_bazaar<'a, FunctionBrand, A, B, S, T, F>(
469		handler: impl Fn(A) -> Apply!(<F as Kind!( type Of<'b, U: 'b>: 'b; )>::Of<'a, B>) + 'a,
470		s: S,
471		bazaar: &Bazaar<'a, FunctionBrand, A, B, S, T>,
472	) -> Apply!(<F as Kind!( type Of<'b, U: 'b>: 'b; )>::Of<'a, T>)
473	where
474		FunctionBrand: CloneableFn + 'static,
475		A: 'a + Clone,
476		B: 'a + Clone,
477		S: 'a,
478		T: 'a,
479		F: crate::classes::Applicative,
480		Apply!(<F as Kind!( type Of<'b, U: 'b>: 'b; )>::Of<'a, B>): Clone,
481		Apply!(<F as Kind!( type Of<'b, U: 'b>: 'b; )>::Of<'a, Vec<B>>): Clone,
482		Apply!(<F as Kind!( type Of<'b, U: 'b>: 'b; )>::Of<'a, T>): Clone, {
483		let bl = (bazaar.run)(s);
484		let f_bs: Vec<Apply!(<F as Kind!( type Of<'b, U: 'b>: 'b; )>::Of<'a, B>)> =
485			bl.foci.into_iter().map(&handler).collect();
486		let f_vec_b: Apply!(<F as Kind!( type Of<'b, U: 'b>: 'b; )>::Of<'a, Vec<B>>) =
487			VecBrand::sequence::<'a, _, F>(f_bs);
488		let rebuild = bl.rebuild;
489		F::map(move |bs| (*rebuild)(bs), f_vec_b)
490	}
491
492	// ── BazaarBrand ─────────────────────────────────────────────────────
493
494	impl_kind! {
495		impl<FunctionBrand: CloneableFn + 'static, A: 'static, B: 'static> for BazaarBrand<FunctionBrand, A, B> {
496			#[document_default]
497			type Of<'a, S: 'a, T: 'a>: 'a = Bazaar<'a, FunctionBrand, A, B, S, T>;
498		}
499	}
500
501	#[document_type_parameters(
502		"The cloneable function brand.",
503		"The focus type.",
504		"The replacement type."
505	)]
506	impl<FunctionBrand: CloneableFn + 'static, A: 'static, B: 'static> Profunctor
507		for BazaarBrand<FunctionBrand, A, B>
508	{
509		/// Maps functions over the input and output of the `Bazaar` profunctor.
510		///
511		/// Corresponds to PureScript's `dimap f g (Bazaar b) = Bazaar \pafb s -> g <$> b pafb (f s)`.
512		#[document_signature]
513		///
514		#[document_type_parameters(
515			"The lifetime of the values.",
516			"The new source type.",
517			"The original source type.",
518			"The original target type.",
519			"The new target type."
520		)]
521		///
522		#[document_parameters(
523			"The contravariant function to apply to the source.",
524			"The covariant function to apply to the target.",
525			"The bazaar instance to transform."
526		)]
527		///
528		#[document_returns("A transformed `Bazaar` instance.")]
529		///
530		#[document_examples]
531		///
532		/// ```
533		/// use fp_library::{
534		/// 	brands::{
535		/// 		optics::*,
536		/// 		*,
537		/// 	},
538		/// 	classes::profunctor::*,
539		/// 	functions::*,
540		/// 	types::optics::*,
541		/// };
542		///
543		/// let bazaar = Bazaar::<RcFnBrand, i32, i32, i32, i32>::new(cloneable_fn_new::<RcFnBrand, _, _>(
544		/// 	|s: i32| BazaarList {
545		/// 		foci: vec![s],
546		/// 		rebuild: cloneable_fn_new::<RcFnBrand, _, _>(|bs: Vec<i32>| bs[0]),
547		/// 	},
548		/// ));
549		/// let dimapped = <BazaarBrand<RcFnBrand, i32, i32> as Profunctor>::dimap(
550		/// 	|s: String| s.parse::<i32>().unwrap(),
551		/// 	|t: i32| t.to_string(),
552		/// 	bazaar,
553		/// );
554		/// let bl = (dimapped.run)("42".to_string());
555		/// assert_eq!(bl.foci, vec![42]);
556		/// assert_eq!((bl.rebuild)(vec![100]), "100".to_string());
557		/// ```
558		fn dimap<'a, S: 'a, T: 'a, U: 'a, V: 'a>(
559			st: impl Fn(S) -> T + 'a,
560			uv: impl Fn(U) -> V + 'a,
561			puv: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, T, U>),
562		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, S, V>) {
563			let run = puv.run;
564			let uv = <FunctionBrand as CloneableFn>::new(uv);
565			Bazaar::new(<FunctionBrand as CloneableFn>::new(move |s: S| {
566				let bl = (*run)(st(s));
567				let rebuild = bl.rebuild;
568				let uv = uv.clone();
569				BazaarList {
570					foci: bl.foci,
571					rebuild: <FunctionBrand as CloneableFn>::new(move |bs: Vec<B>| {
572						(*uv)((*rebuild)(bs))
573					}),
574				}
575			}))
576		}
577	}
578
579	#[document_type_parameters(
580		"The cloneable function brand.",
581		"The focus type.",
582		"The replacement type."
583	)]
584	impl<FunctionBrand: CloneableFn + 'static, A: 'static, B: 'static> Strong
585		for BazaarBrand<FunctionBrand, A, B>
586	{
587		/// Lifts the `Bazaar` profunctor to operate on the first component of a tuple.
588		///
589		/// Corresponds to PureScript's `first (Bazaar b) = Bazaar (\pafb (Tuple x y) -> flip Tuple y <$> b pafb x)`.
590		#[document_signature]
591		///
592		#[document_type_parameters(
593			"The lifetime of the values.",
594			"The source type.",
595			"The target type.",
596			"The type of the second component."
597		)]
598		///
599		#[document_parameters("The bazaar instance to lift.")]
600		///
601		#[document_returns("A `Bazaar` that operates on pairs.")]
602		///
603		#[document_examples]
604		///
605		/// ```
606		/// use fp_library::{
607		/// 	brands::{
608		/// 		optics::*,
609		/// 		*,
610		/// 	},
611		/// 	classes::profunctor::*,
612		/// 	functions::*,
613		/// 	types::optics::*,
614		/// };
615		///
616		/// let bazaar = Bazaar::<RcFnBrand, i32, i32, i32, i32>::new(cloneable_fn_new::<RcFnBrand, _, _>(
617		/// 	|s: i32| BazaarList {
618		/// 		foci: vec![s],
619		/// 		rebuild: cloneable_fn_new::<RcFnBrand, _, _>(|bs: Vec<i32>| bs[0]),
620		/// 	},
621		/// ));
622		/// let lifted = <BazaarBrand<RcFnBrand, i32, i32> as Strong>::first::<i32, i32, String>(bazaar);
623		/// let bl = (lifted.run)((42, "hello".to_string()));
624		/// assert_eq!(bl.foci, vec![42]);
625		/// assert_eq!((bl.rebuild)(vec![100]), (100, "hello".to_string()));
626		/// ```
627		fn first<'a, S: 'a, T: 'a, C: 'a>(
628			pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, S, T>)
629		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, (S, C), (T, C)>) {
630			let run = pab.run;
631			Bazaar::new(<FunctionBrand as CloneableFn>::new(move |(s, c): (S, C)| {
632				let bl = (*run)(s);
633				let rebuild = bl.rebuild;
634				let c = Ptr::<FunctionBrand>::take_cell_new(c);
635				BazaarList {
636					foci: bl.foci,
637					rebuild: <FunctionBrand as CloneableFn>::new(move |bs: Vec<B>| {
638						// SAFETY: take_cell_take is called exactly once per the optics rebuild contract
639						#[allow(clippy::expect_used)]
640						let c = Ptr::<FunctionBrand>::take_cell_take(&c)
641							.expect("BazaarList rebuild called more than once");
642						((*rebuild)(bs), c)
643					}),
644				}
645			}))
646		}
647
648		/// Lifts the `Bazaar` profunctor to operate on the second component of a tuple.
649		///
650		/// Corresponds to PureScript's `second (Bazaar b) = Bazaar (\pafb (Tuple x y) -> Tuple x <$> b pafb y)`.
651		#[document_signature]
652		///
653		#[document_type_parameters(
654			"The lifetime of the values.",
655			"The source type.",
656			"The target type.",
657			"The type of the first component."
658		)]
659		///
660		#[document_parameters("The bazaar instance to lift.")]
661		///
662		#[document_returns("A `Bazaar` that operates on pairs.")]
663		///
664		#[document_examples]
665		///
666		/// ```
667		/// use fp_library::{
668		/// 	brands::{
669		/// 		optics::*,
670		/// 		*,
671		/// 	},
672		/// 	classes::profunctor::*,
673		/// 	functions::*,
674		/// 	types::optics::*,
675		/// };
676		///
677		/// let bazaar = Bazaar::<RcFnBrand, i32, i32, i32, i32>::new(cloneable_fn_new::<RcFnBrand, _, _>(
678		/// 	|s: i32| BazaarList {
679		/// 		foci: vec![s],
680		/// 		rebuild: cloneable_fn_new::<RcFnBrand, _, _>(|bs: Vec<i32>| bs[0]),
681		/// 	},
682		/// ));
683		/// let lifted = <BazaarBrand<RcFnBrand, i32, i32> as Strong>::second::<i32, i32, String>(bazaar);
684		/// let bl = (lifted.run)(("hello".to_string(), 42));
685		/// assert_eq!(bl.foci, vec![42]);
686		/// assert_eq!((bl.rebuild)(vec![100]), ("hello".to_string(), 100));
687		/// ```
688		fn second<'a, S: 'a, T: 'a, C: 'a>(
689			pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, S, T>)
690		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, (C, S), (C, T)>) {
691			let run = pab.run;
692			Bazaar::new(<FunctionBrand as CloneableFn>::new(move |(c, s): (C, S)| {
693				let bl = (*run)(s);
694				let rebuild = bl.rebuild;
695				let c = Ptr::<FunctionBrand>::take_cell_new(c);
696				BazaarList {
697					foci: bl.foci,
698					rebuild: <FunctionBrand as CloneableFn>::new(move |bs: Vec<B>| {
699						// SAFETY: take_cell_take is called exactly once per the optics rebuild contract
700						#[allow(clippy::expect_used)]
701						let c = Ptr::<FunctionBrand>::take_cell_take(&c)
702							.expect("BazaarList rebuild called more than once");
703						(c, (*rebuild)(bs))
704					}),
705				}
706			}))
707		}
708	}
709
710	#[document_type_parameters(
711		"The cloneable function brand.",
712		"The focus type.",
713		"The replacement type."
714	)]
715	impl<FunctionBrand: CloneableFn + 'static, A: 'static, B: 'static> Choice
716		for BazaarBrand<FunctionBrand, A, B>
717	{
718		/// Lifts the `Bazaar` profunctor to operate on the `Err` variant of a `Result`.
719		///
720		/// Corresponds to PureScript's `left (Bazaar b) = Bazaar (\pafb e -> bitraverse (b pafb) pure e)`.
721		#[document_signature]
722		///
723		#[document_type_parameters(
724			"The lifetime of the values.",
725			"The source type.",
726			"The target type.",
727			"The type of the `Ok` variant."
728		)]
729		///
730		#[document_parameters("The bazaar instance to lift.")]
731		///
732		#[document_returns("A `Bazaar` that operates on `Result` types.")]
733		///
734		#[document_examples]
735		///
736		/// ```
737		/// use fp_library::{
738		/// 	brands::{
739		/// 		optics::*,
740		/// 		*,
741		/// 	},
742		/// 	classes::profunctor::*,
743		/// 	functions::*,
744		/// 	types::optics::*,
745		/// };
746		///
747		/// let bazaar = Bazaar::<RcFnBrand, i32, i32, i32, i32>::new(cloneable_fn_new::<RcFnBrand, _, _>(
748		/// 	|s: i32| BazaarList {
749		/// 		foci: vec![s],
750		/// 		rebuild: cloneable_fn_new::<RcFnBrand, _, _>(|bs: Vec<i32>| bs[0]),
751		/// 	},
752		/// ));
753		/// let lifted = <BazaarBrand<RcFnBrand, i32, i32> as Choice>::left::<i32, i32, String>(bazaar);
754		/// let bl_err = (lifted.run)(Err(42));
755		/// assert_eq!(bl_err.foci, vec![42]);
756		/// assert_eq!((bl_err.rebuild)(vec![100]), Err(100));
757		/// let bl_ok = (lifted.run)(Ok("hello".to_string()));
758		/// assert_eq!(bl_ok.foci.len(), 0);
759		/// assert_eq!((bl_ok.rebuild)(vec![]), Ok("hello".to_string()));
760		/// ```
761		fn left<'a, S: 'a, T: 'a, C: 'a>(
762			pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, S, T>)
763		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, Result<C, S>, Result<C, T>>)
764		{
765			let run = pab.run;
766			Bazaar::new(<FunctionBrand as CloneableFn>::new(move |r: Result<C, S>| match r {
767				Err(s) => {
768					let bl = (*run)(s);
769					let rebuild = bl.rebuild;
770					BazaarList {
771						foci: bl.foci,
772						rebuild: <FunctionBrand as CloneableFn>::new(move |bs: Vec<B>| {
773							Err((*rebuild)(bs))
774						}),
775					}
776				}
777				Ok(c) => {
778					let c = Ptr::<FunctionBrand>::take_cell_new(c);
779					BazaarList {
780						foci: vec![],
781						rebuild: <FunctionBrand as CloneableFn>::new(move |_: Vec<B>| {
782							// SAFETY: take_cell_take is called exactly once per the optics rebuild contract
783							#[allow(clippy::expect_used)]
784							Ok(Ptr::<FunctionBrand>::take_cell_take(&c)
785								.expect("BazaarList rebuild called more than once"))
786						}),
787					}
788				}
789			}))
790		}
791
792		/// Lifts the `Bazaar` profunctor to operate on the `Ok` variant of a `Result`.
793		///
794		/// Corresponds to PureScript's `right (Bazaar b) = Bazaar (\pafb e -> traverse (b pafb) e)`.
795		#[document_signature]
796		///
797		#[document_type_parameters(
798			"The lifetime of the values.",
799			"The source type.",
800			"The target type.",
801			"The type of the `Err` variant."
802		)]
803		///
804		#[document_parameters("The bazaar instance to lift.")]
805		///
806		#[document_returns("A `Bazaar` that operates on `Result` types.")]
807		///
808		#[document_examples]
809		///
810		/// ```
811		/// use fp_library::{
812		/// 	brands::{
813		/// 		optics::*,
814		/// 		*,
815		/// 	},
816		/// 	classes::profunctor::*,
817		/// 	functions::*,
818		/// 	types::optics::*,
819		/// };
820		///
821		/// let bazaar = Bazaar::<RcFnBrand, i32, i32, i32, i32>::new(cloneable_fn_new::<RcFnBrand, _, _>(
822		/// 	|s: i32| BazaarList {
823		/// 		foci: vec![s],
824		/// 		rebuild: cloneable_fn_new::<RcFnBrand, _, _>(|bs: Vec<i32>| bs[0]),
825		/// 	},
826		/// ));
827		/// let lifted = <BazaarBrand<RcFnBrand, i32, i32> as Choice>::right::<i32, i32, String>(bazaar);
828		/// let bl_ok = (lifted.run)(Ok(42));
829		/// assert_eq!(bl_ok.foci, vec![42]);
830		/// assert_eq!((bl_ok.rebuild)(vec![100]), Ok(100));
831		/// let bl_err = (lifted.run)(Err("oops".to_string()));
832		/// assert_eq!(bl_err.foci.len(), 0);
833		/// assert_eq!((bl_err.rebuild)(vec![]), Err("oops".to_string()));
834		/// ```
835		fn right<'a, S: 'a, T: 'a, C: 'a>(
836			pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, S, T>)
837		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, Result<S, C>, Result<T, C>>)
838		{
839			let run = pab.run;
840			Bazaar::new(<FunctionBrand as CloneableFn>::new(move |r: Result<S, C>| match r {
841				Ok(s) => {
842					let bl = (*run)(s);
843					let rebuild = bl.rebuild;
844					BazaarList {
845						foci: bl.foci,
846						rebuild: <FunctionBrand as CloneableFn>::new(move |bs: Vec<B>| {
847							Ok((*rebuild)(bs))
848						}),
849					}
850				}
851				Err(c) => {
852					let c = Ptr::<FunctionBrand>::take_cell_new(c);
853					BazaarList {
854						foci: vec![],
855						rebuild: <FunctionBrand as CloneableFn>::new(move |_: Vec<B>| {
856							// SAFETY: take_cell_take is called exactly once per the optics rebuild contract
857							#[allow(clippy::expect_used)]
858							Err(Ptr::<FunctionBrand>::take_cell_take(&c)
859								.expect("BazaarList rebuild called more than once"))
860						}),
861					}
862				}
863			}))
864		}
865	}
866
867	#[document_type_parameters(
868		"The cloneable function brand.",
869		"The focus type.",
870		"The replacement type."
871	)]
872	impl<FunctionBrand: CloneableFn + 'static, A: 'static + Clone, B: 'static + Clone> Wander
873		for BazaarBrand<FunctionBrand, A, B>
874	{
875		/// Lifts the `Bazaar` profunctor through a traversal.
876		///
877		/// Corresponds to PureScript's `wander w (Bazaar f) = Bazaar (\pafb s -> w (f pafb) s)`.
878		/// Uses `BazaarListBrand` as the applicative to decompose the traversal structure.
879		#[document_signature]
880		///
881		#[document_type_parameters(
882			"The lifetime of the values.",
883			"The outer source type.",
884			"The outer target type.",
885			"The inner source type (focus of the traversal).",
886			"The inner target type."
887		)]
888		///
889		#[document_parameters("The traversal function.", "The bazaar instance to compose with.")]
890		///
891		#[document_returns("A `Bazaar` that traverses the outer structure.")]
892		///
893		#[document_examples]
894		///
895		/// ```
896		/// use fp_library::{
897		/// 	Apply,
898		/// 	brands::{
899		/// 		optics::*,
900		/// 		*,
901		/// 	},
902		/// 	classes::{
903		/// 		Applicative,
904		/// 		optics::traversal::TraversalFunc,
905		/// 		profunctor::*,
906		/// 	},
907		/// 	functions::*,
908		/// 	kinds::*,
909		/// 	types::optics::*,
910		/// };
911		///
912		/// // A traversal over Vec elements
913		/// #[derive(Clone)]
914		/// struct VecTraversal;
915		/// impl<'a, X: 'a + Clone> TraversalFunc<'a, Vec<X>, Vec<X>, X, X> for VecTraversal {
916		/// 	fn apply<M: Applicative>(
917		/// 		&self,
918		/// 		f: Box<dyn Fn(X) -> Apply!(<M as Kind!( type Of<'b, U: 'b>: 'b; )>::Of<'a, X>) + 'a>,
919		/// 		s: Vec<X>,
920		/// 	) -> Apply!(<M as Kind!( type Of<'b, U: 'b>: 'b; )>::Of<'a, Vec<X>>) {
921		/// 		s.into_iter().fold(M::pure(vec![]), |acc, a| {
922		/// 			M::lift2(
923		/// 				|mut v: Vec<X>, x: X| {
924		/// 					v.push(x);
925		/// 					v
926		/// 				},
927		/// 				acc,
928		/// 				f(a),
929		/// 			)
930		/// 		})
931		/// 	}
932		/// }
933		///
934		/// // Identity bazaar: each element maps to itself
935		/// let id_bazaar = Bazaar::<RcFnBrand, i32, i32, i32, i32>::new(
936		/// 	cloneable_fn_new::<RcFnBrand, _, _>(|s: i32| BazaarList {
937		/// 		foci: vec![s],
938		/// 		rebuild: cloneable_fn_new::<RcFnBrand, _, _>(|bs: Vec<i32>| bs[0]),
939		/// 	}),
940		/// );
941		/// let wandered =
942		/// 	<BazaarBrand<RcFnBrand, i32, i32> as Wander>::wander::<Vec<i32>, Vec<i32>, i32, i32>(
943		/// 		VecTraversal,
944		/// 		id_bazaar,
945		/// 	);
946		/// let bl = (wandered.run)(vec![10, 20, 30]);
947		/// assert_eq!(bl.foci, vec![10, 20, 30]);
948		/// assert_eq!((bl.rebuild)(vec![1, 2, 3]), vec![1, 2, 3]);
949		/// ```
950		fn wander<'a, S: 'a, T: 'a, A2: 'a, B2: 'a + Clone>(
951			traversal: impl TraversalFunc<'a, S, T, A2, B2> + 'a,
952			pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A2, B2>),
953		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, S, T>) {
954			let run = pab.run;
955			Bazaar::new(<FunctionBrand as CloneableFn>::new(move |s: S| {
956				let run = run.clone();
957				traversal.apply::<BazaarListBrand<FunctionBrand, A, B>>(
958					Box::new(move |a2: A2| (*run)(a2)),
959					s,
960				)
961			}))
962		}
963	}
964}
965pub use inner::*;
966
967impl<'a, FB: crate::classes::cloneable_fn::CloneableFn + 'static, A: Clone + 'a, B: 'a, T: 'a> Clone
968	for BazaarList<'a, FB, A, B, T>
969where
970	<FB as crate::classes::cloneable_fn::CloneableFn>::Of<'a, Vec<B>, T>: Clone,
971{
972	fn clone(&self) -> Self {
973		BazaarList {
974			foci: self.foci.clone(),
975			rebuild: self.rebuild.clone(),
976		}
977	}
978}