1#[fp_macros::document_module]
6mod inner {
7 use {
8 crate::{
9 Apply,
10 brands::optics::*,
11 classes::{
12 applicative::Applicative,
13 profunctor::{
14 Choice,
15 Profunctor,
16 Strong,
17 Wander,
18 wander::TraversalFunc,
19 },
20 },
21 impl_kind,
22 kinds::*,
23 },
24 fp_macros::*,
25 std::marker::PhantomData,
26 };
27
28 #[document_type_parameters(
32 "The lifetime of the values.",
33 "The underlying profunctor brand.",
34 "The index type.",
35 "The focus type.",
36 "The target focus type."
37 )]
38 pub struct Indexed<'a, P, I, A, B>
39 where
40 P: Profunctor,
41 I: 'a,
42 A: 'a,
43 B: 'a, {
44 pub inner: Apply!(<P as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, (I, A), B>),
46 }
47
48 #[document_type_parameters(
49 "The lifetime of the values.",
50 "The underlying profunctor brand.",
51 "The index type.",
52 "The focus type.",
53 "The target focus type."
54 )]
55 impl<'a, P, I, A, B> Indexed<'a, P, I, A, B>
56 where
57 P: Profunctor,
58 I: 'a,
59 A: 'a,
60 B: 'a,
61 {
62 #[document_signature]
64 #[document_parameters("The underlying profunctor value.")]
65 #[document_returns("A new `Indexed` instance.")]
66 #[document_examples]
67 pub fn new(
78 inner: Apply!(<P as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, (I, A), B>)
79 ) -> Self {
80 Self {
81 inner,
82 }
83 }
84 }
85
86 impl_kind! {
87 impl<P: Profunctor + 'static, I: 'static> for IndexedBrand<P, I> {
88 #[document_default]
89 type Of<'a, A: 'a, B: 'a>: 'a = Indexed<'a, P, I, A, B>;
90 }
91 }
92
93 #[document_type_parameters("The underlying profunctor brand.", "The index type.")]
94 impl<P: Profunctor + 'static, I: 'static> Profunctor for IndexedBrand<P, I> {
95 #[document_signature]
96 #[document_type_parameters(
97 "The lifetime of the values.",
98 "The new input type.",
99 "The original input type.",
100 "The original output type.",
101 "The new output type."
102 )]
103 #[document_parameters(
104 "The contravariant function to apply to the input.",
105 "The covariant function to apply to the output.",
106 "The indexed profunctor instance."
107 )]
108 #[document_returns("A transformed `Indexed` instance.")]
109 #[document_examples]
110 fn dimap<'a, A: 'a, B: 'a, C: 'a, D: 'a>(
130 ab: impl Fn(A) -> B + 'a,
131 cd: impl Fn(C) -> D + 'a,
132 pbc: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, B, C>),
133 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A, D>) {
134 Indexed::new(P::dimap(move |(i, a)| (i, ab(a)), cd, pbc.inner))
135 }
136 }
137
138 #[document_type_parameters("The underlying profunctor brand.", "The index type.")]
139 impl<P: Strong + 'static, I: 'static> Strong for IndexedBrand<P, I> {
140 #[document_signature]
141 #[document_type_parameters(
142 "The lifetime of the values.",
143 "The input type of the profunctor.",
144 "The output type of the profunctor.",
145 "The type of the second component (threaded through unchanged)."
146 )]
147 #[document_parameters("The indexed profunctor instance to lift.")]
148 #[document_returns("A transformed `Indexed` instance that operates on pairs.")]
149 #[document_examples]
150 fn first<'a, A: 'a, B: 'a, C>(
164 pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A, B>)
165 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, (A, C), (B, C)>) {
166 Indexed::new(P::dimap(
167 |(i, (a, c))| ((i, a), c),
168 |(b, c)| (b, c),
169 P::first::<(I, A), B, C>(pab.inner),
170 ))
171 }
172
173 #[document_signature]
174 #[document_type_parameters(
175 "The lifetime of the values.",
176 "The input type of the profunctor.",
177 "The output type of the profunctor.",
178 "The type of the first component (threaded through unchanged)."
179 )]
180 #[document_parameters("The indexed profunctor instance to lift.")]
181 #[document_returns("A transformed `Indexed` instance that operates on pairs.")]
182 #[document_examples]
183 fn second<'a, A: 'a, B: 'a, C: 'a>(
197 pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A, B>)
198 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, (C, A), (C, B)>) {
199 Indexed::new(P::dimap(
200 |(i, (c, a))| (c, (i, a)),
201 |(c, b)| (c, b),
202 P::second::<(I, A), B, C>(pab.inner),
203 ))
204 }
205 }
206
207 #[document_type_parameters("The underlying profunctor brand.", "The index type.")]
208 impl<P: Choice + 'static, I: 'static> Choice for IndexedBrand<P, I> {
209 #[document_signature]
210 #[document_type_parameters(
211 "The lifetime of the values.",
212 "The input type of the profunctor.",
213 "The output type of the profunctor.",
214 "The type of the alternative variant (threaded through unchanged)."
215 )]
216 #[document_parameters("The indexed profunctor instance to lift.")]
217 #[document_returns("A transformed `Indexed` instance that operates on `Result` types.")]
218 #[document_examples]
219 fn left<'a, A: 'a, B: 'a, C: 'a>(
235 pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A, B>)
236 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, Result<C, A>, Result<C, B>>)
237 {
238 Indexed::new(P::dimap(
239 |(i, r)| match r {
240 Err(a) => Err((i, a)),
241 Ok(c) => Ok(c),
242 },
243 |r| match r {
244 Err(b) => Err(b),
245 Ok(c) => Ok(c),
246 },
247 P::left::<(I, A), B, C>(pab.inner),
248 ))
249 }
250
251 #[document_signature]
252 #[document_type_parameters(
253 "The lifetime of the values.",
254 "The input type of the profunctor.",
255 "The output type of the profunctor.",
256 "The type of the alternative variant (threaded through unchanged)."
257 )]
258 #[document_parameters("The indexed profunctor instance to lift.")]
259 #[document_returns("A transformed `Indexed` instance that operates on `Result` types.")]
260 #[document_examples]
261 fn right<'a, A: 'a, B: 'a, C: 'a>(
277 pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A, B>)
278 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, Result<A, C>, Result<B, C>>)
279 {
280 Indexed::new(P::dimap(
281 |(i, r)| match r {
282 Ok(a) => Ok((i, a)),
283 Err(c) => Err(c),
284 },
285 |r| match r {
286 Ok(b) => Ok(b),
287 Err(c) => Err(c),
288 },
289 P::right::<(I, A), B, C>(pab.inner),
290 ))
291 }
292 }
293
294 #[document_type_parameters("The underlying profunctor brand.", "The index type.")]
295 impl<P: Wander + 'static, I: Clone + 'static> Wander for IndexedBrand<P, I> {
296 #[document_signature]
297 #[document_type_parameters(
298 "The lifetime of the values.",
299 "The source type of the structure.",
300 "The target type of the structure.",
301 "The source type of the focus.",
302 "The target type of the focus."
303 )]
304 #[document_parameters("The traversal function.", "The indexed profunctor instance.")]
305 #[document_returns("A transformed `Indexed` instance that operates on structures.")]
306 #[document_examples]
307 fn wander<'a, S: 'a, T: 'a, A: 'a, B: 'a + Clone>(
341 traversal: impl TraversalFunc<'a, S, T, A, B> + 'a,
342 pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A, B>),
343 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, S, T>) {
344 struct IWanderAdapter<'a, I, S, T, A, B, TFunc> {
345 traversal: TFunc,
346 _phantom: PhantomData<&'a (I, S, T, A, B)>,
347 }
348
349 impl<'a, I: Clone + 'a, S: 'a, T: 'a, A: 'a, B: 'a, TFunc>
350 TraversalFunc<'a, (I, S), T, (I, A), B> for IWanderAdapter<'a, I, S, T, A, B, TFunc>
351 where
352 TFunc: TraversalFunc<'a, S, T, A, B> + 'a,
353 {
354 fn apply<M: Applicative>(
355 &self,
356 f: Box<
357 dyn Fn((I, A)) -> Apply!(<M as Kind!( type Of<'c, U: 'c>: 'c; )>::Of<'a, B>)
358 + 'a,
359 >,
360 (i, s): (I, S),
361 ) -> Apply!(<M as Kind!( type Of<'c, U: 'c>: 'c; )>::Of<'a, T>)
362 where
363 Apply!(<M as Kind!( type Of<'c, U: 'c>: 'c; )>::Of<'a, B>): Clone, {
364 let i_clone = i.clone();
365 self.traversal.apply::<M>(Box::new(move |a| f((i_clone.clone(), a))), s)
366 }
367 }
368
369 Indexed::new(P::wander(
370 IWanderAdapter {
371 traversal,
372 _phantom: PhantomData,
373 },
374 pab.inner,
375 ))
376 }
377 }
378}
379
380pub use inner::*;