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