1#[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 Ptr<FunctionBrand> = <FunctionBrand as CloneFn>::PointerBrand;
41
42 #[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 pub foci: Vec<A>,
59 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 #[document_signature]
79 #[document_type_parameters(
81 "The lifetime of the values.",
82 "The original result type.",
83 "The new result type."
84 )]
85 #[document_parameters("The function to apply.", "The bazaar list to map over.")]
87 #[document_returns("A new `BazaarList` with the same foci but a transformed rebuild.")]
89 #[document_examples]
91 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 #[document_signature]
132 #[document_type_parameters("The lifetime of the value.", "The type of the value.")]
134 #[document_parameters("The value to wrap.")]
136 #[document_returns("A `BazaarList` with empty foci that ignores its input.")]
138 #[document_examples]
140 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 #[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 #[document_signature]
184 #[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 #[document_parameters(
193 "The binary function to combine results.",
194 "The first `BazaarList`.",
195 "The second `BazaarList`."
196 )]
197 #[document_returns(
199 "A `BazaarList` with concatenated foci whose rebuild splits and delegates."
200 )]
201 #[document_examples]
203 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 #[document_signature]
264 #[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 #[document_parameters(
273 "The `BazaarList` containing the function.",
274 "The `BazaarList` containing the value."
275 )]
276 #[document_returns("A `BazaarList` with the function applied.")]
278 #[document_examples]
280 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 #[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 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 #[document_signature]
376 #[document_parameters("The decomposition function from source to `BazaarList`.")]
378 #[document_returns("A new instance of the type.")]
380 #[document_examples]
382 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 #[document_signature]
418 #[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 #[document_parameters(
430 "The handler function that lifts each focus into the applicative.",
431 "The source value.",
432 "The bazaar to interpret."
433 )]
434 #[document_returns("The target wrapped in the applicative context.")]
436 #[document_examples]
438 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 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 #[document_signature]
513 #[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 #[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 #[document_returns("A transformed `Bazaar` instance.")]
529 #[document_examples]
531 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 #[document_signature]
592 #[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 #[document_parameters("The bazaar instance to lift.")]
601 #[document_returns("A `Bazaar` that operates on pairs.")]
603 #[document_examples]
605 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 #[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 #[document_signature]
657 #[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 #[document_parameters("The bazaar instance to lift.")]
666 #[document_returns("A `Bazaar` that operates on pairs.")]
668 #[document_examples]
670 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 #[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 #[document_signature]
731 #[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 #[document_parameters("The bazaar instance to lift.")]
740 #[document_returns("A `Bazaar` that operates on `Result` types.")]
742 #[document_examples]
744 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 #[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 #[document_signature]
809 #[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 #[document_parameters("The bazaar instance to lift.")]
818 #[document_returns("A `Bazaar` that operates on `Result` types.")]
820 #[document_examples]
822 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 #[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 #[document_signature]
897 #[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 #[document_parameters("The traversal function.", "The bazaar instance to compose with.")]
907 #[document_returns("A `Bazaar` that traverses the outer structure.")]
909 #[document_examples]
911 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}