1#[fp_macros::document_module]
17mod inner {
18 use {
19 crate::{
20 brands::*,
21 classes::*,
22 kinds::*,
23 },
24 fp_macros::*,
25 };
26
27 #[document_examples]
47 #[kind(type Of<'a, A: 'a, B: 'a>: 'a;)]
81 pub trait RefBifunctor {
82 #[document_signature]
87 #[document_type_parameters(
89 "The lifetime of the values.",
90 "The type of the first value.",
91 "The type of the first result.",
92 "The type of the second value.",
93 "The type of the second result."
94 )]
95 #[document_parameters(
97 "The function to apply to the first value.",
98 "The function to apply to the second value.",
99 "The bifunctor instance (borrowed)."
100 )]
101 #[document_returns(
103 "A new bifunctor instance containing the results of applying the functions."
104 )]
105 #[document_examples]
106 fn ref_bimap<'a, A: 'a, B: 'a, C: 'a, D: 'a>(
118 f: impl Fn(&A) -> B + 'a,
119 g: impl Fn(&C) -> D + 'a,
120 p: &Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, C>),
121 ) -> Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, B, D>);
122
123 #[document_signature]
129 #[document_type_parameters(
131 "The lifetime of the values.",
132 "The type of the first value.",
133 "The type of the first result.",
134 "The type of the second value (must be Clone)."
135 )]
136 #[document_parameters(
138 "The function to apply to the first value.",
139 "The bifunctor instance (borrowed)."
140 )]
141 #[document_returns("A new bifunctor instance with the first value transformed.")]
143 #[document_examples]
144 fn ref_map_first<'a, A: 'a, B: 'a, C: Clone + 'a>(
160 f: impl Fn(&A) -> B + 'a,
161 p: &Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, C>),
162 ) -> Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, B, C>) {
163 Self::ref_bimap(f, |c: &C| c.clone(), p)
164 }
165
166 #[document_signature]
172 #[document_type_parameters(
174 "The lifetime of the values.",
175 "The type of the first value (must be Clone).",
176 "The type of the second value.",
177 "The type of the second result."
178 )]
179 #[document_parameters(
181 "The function to apply to the second value.",
182 "The bifunctor instance (borrowed)."
183 )]
184 #[document_returns("A new bifunctor instance with the second value transformed.")]
186 #[document_examples]
187 fn ref_map_second<'a, A: Clone + 'a, B: 'a, C: 'a>(
203 g: impl Fn(&B) -> C + 'a,
204 p: &Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
205 ) -> Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, C>) {
206 Self::ref_bimap(|a: &A| a.clone(), g, p)
207 }
208 }
209
210 #[document_signature]
214 #[document_type_parameters(
216 "The lifetime of the values.",
217 "The brand of the bifunctor.",
218 "The type of the first value.",
219 "The type of the first result.",
220 "The type of the second value.",
221 "The type of the second result."
222 )]
223 #[document_parameters(
225 "The function to apply to the first value.",
226 "The function to apply to the second value.",
227 "The bifunctor instance (borrowed)."
228 )]
229 #[document_returns(
231 "A new bifunctor instance containing the results of applying the functions."
232 )]
233 #[document_examples]
234 pub fn ref_bimap<'a, Brand: RefBifunctor, A: 'a, B: 'a, C: 'a, D: 'a>(
246 f: impl Fn(&A) -> B + 'a,
247 g: impl Fn(&C) -> D + 'a,
248 p: &Apply!(<Brand as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, C>),
249 ) -> Apply!(<Brand as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, B, D>) {
250 Brand::ref_bimap(f, g, p)
251 }
252
253 #[document_signature]
257 #[document_type_parameters(
259 "The lifetime of the values.",
260 "The brand of the bifunctor.",
261 "The type of the first value.",
262 "The type of the first result.",
263 "The type of the second value (must be Clone)."
264 )]
265 #[document_parameters(
267 "The function to apply to the first value.",
268 "The bifunctor instance (borrowed)."
269 )]
270 #[document_returns("A new bifunctor instance with the first value transformed.")]
272 #[document_examples]
273 pub fn ref_map_first<'a, Brand: RefBifunctor, A: 'a, B: 'a, C: Clone + 'a>(
285 f: impl Fn(&A) -> B + 'a,
286 p: &Apply!(<Brand as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, C>),
287 ) -> Apply!(<Brand as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, B, C>) {
288 Brand::ref_map_first(f, p)
289 }
290
291 #[document_signature]
295 #[document_type_parameters(
297 "The lifetime of the values.",
298 "The brand of the bifunctor.",
299 "The type of the first value (must be Clone).",
300 "The type of the second value.",
301 "The type of the second result."
302 )]
303 #[document_parameters(
305 "The function to apply to the second value.",
306 "The bifunctor instance (borrowed)."
307 )]
308 #[document_returns("A new bifunctor instance with the second value transformed.")]
310 #[document_examples]
311 pub fn ref_map_second<'a, Brand: RefBifunctor, A: Clone + 'a, B: 'a, C: 'a>(
323 g: impl Fn(&B) -> C + 'a,
324 p: &Apply!(<Brand as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
325 ) -> Apply!(<Brand as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, C>) {
326 Brand::ref_map_second(g, p)
327 }
328
329 #[document_type_parameters("The bifunctor brand.", "The fixed second type parameter.")]
336 impl<Brand: Bifunctor + RefBifunctor, A: Clone + 'static> RefFunctor
337 for BifunctorFirstAppliedBrand<Brand, A>
338 {
339 #[document_signature]
341 #[document_type_parameters(
342 "The lifetime of the values.",
343 "The input type.",
344 "The output type."
345 )]
346 #[document_parameters("The function to apply.", "The bifunctor value to map over.")]
347 #[document_returns("The mapped bifunctor value.")]
348 #[document_examples]
349 fn ref_map<'a, B: 'a, C: 'a>(
361 func: impl Fn(&B) -> C + 'a,
362 fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
363 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>) {
364 Brand::ref_bimap(|a: &A| a.clone(), func, fa)
365 }
366 }
367
368 #[document_type_parameters("The bifunctor brand.", "The fixed first type parameter.")]
375 impl<Brand: Bifunctor + RefBifunctor, B: Clone + 'static> RefFunctor
376 for BifunctorSecondAppliedBrand<Brand, B>
377 {
378 #[document_signature]
380 #[document_type_parameters(
381 "The lifetime of the values.",
382 "The input type.",
383 "The output type."
384 )]
385 #[document_parameters("The function to apply.", "The bifunctor value to map over.")]
386 #[document_returns("The mapped bifunctor value.")]
387 #[document_examples]
388 fn ref_map<'a, A: 'a, C: 'a>(
400 func: impl Fn(&A) -> C + 'a,
401 fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
402 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>) {
403 Brand::ref_bimap(func, |b: &B| b.clone(), fa)
404 }
405 }
406}
407
408pub use inner::*;
409
410#[cfg(test)]
411mod tests {
412 use {
413 crate::{
414 brands::*,
415 functions::explicit::*,
416 },
417 quickcheck_macros::quickcheck,
418 };
419
420 #[quickcheck]
422 fn prop_ref_bifunctor_identity(
423 a: i32,
424 c: i32,
425 ) -> bool {
426 let ok: Result<i32, i32> = Ok(c);
427 let err: Result<i32, i32> = Err(a);
428 bimap::<ResultBrand, _, _, _, _, _, _>((|x: &i32| *x, |x: &i32| *x), &ok) == ok
429 && bimap::<ResultBrand, _, _, _, _, _, _>((|x: &i32| *x, |x: &i32| *x), &err) == err
430 }
431
432 #[quickcheck]
434 fn prop_ref_bifunctor_composition(
435 a: i32,
436 c: i32,
437 ) -> bool {
438 let f1 = |x: &i32| x.wrapping_add(1);
439 let f2 = |x: &i32| x.wrapping_mul(2);
440 let g1 = |x: &i32| x.wrapping_add(10);
441 let g2 = |x: &i32| x.wrapping_mul(3);
442
443 let ok: Result<i32, i32> = Ok(c);
444 let err: Result<i32, i32> = Err(a);
445
446 let composed_ok = bimap::<ResultBrand, _, _, _, _, _, _>(
447 (|x: &i32| f2(&f1(x)), |x: &i32| g2(&g1(x))),
448 &ok,
449 );
450 let sequential_ok = bimap::<ResultBrand, _, _, _, _, _, _>(
451 (f2, g2),
452 &bimap::<ResultBrand, _, _, _, _, _, _>((f1, g1), &ok),
453 );
454
455 let composed_err = bimap::<ResultBrand, _, _, _, _, _, _>(
456 (|x: &i32| f2(&f1(x)), |x: &i32| g2(&g1(x))),
457 &err,
458 );
459 let sequential_err = bimap::<ResultBrand, _, _, _, _, _, _>(
460 (f2, g2),
461 &bimap::<ResultBrand, _, _, _, _, _, _>((f1, g1), &err),
462 );
463
464 composed_ok == sequential_ok && composed_err == sequential_err
465 }
466}