fp_library/types/pair.rs
1use crate::{
2 Apply,
3 brands::{PairBrand, PairWithFirstBrand, PairWithSecondBrand},
4 classes::{
5 applicative::Applicative, apply_first::ApplyFirst, apply_second::ApplySecond,
6 bifunctor::Bifunctor, cloneable_fn::CloneableFn, foldable::Foldable, functor::Functor,
7 lift::Lift, monoid::Monoid, par_foldable::ParFoldable, pointed::Pointed,
8 semiapplicative::Semiapplicative, semigroup::Semigroup, semimonad::Semimonad,
9 send_cloneable_fn::SendCloneableFn, traversable::Traversable,
10 },
11 impl_kind,
12 kinds::*,
13};
14
15/// Wraps two values.
16///
17/// A simple tuple struct that holds two values of potentially different types.
18///
19/// ### Type Parameters
20///
21/// * `First`: The type of the first value.
22/// * `Second`: The type of the second value.
23///
24/// ### Fields
25///
26/// * `0`: The first value.
27/// * `1`: The second value.
28///
29/// ### Examples
30///
31/// ```
32/// use fp_library::types::*;
33///
34/// let p = Pair(1, "hello");
35/// assert_eq!(p.0, 1);
36/// assert_eq!(p.1, "hello");
37/// ```
38#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
39pub struct Pair<First, Second>(pub First, pub Second);
40
41impl_kind! {
42 for PairBrand {
43 type Of<A, B> = Pair<A, B>;
44 }
45}
46
47impl_kind! {
48 for PairBrand {
49 type Of<'a, A: 'a, B: 'a>: 'a = Pair<A, B>;
50 }
51}
52
53impl Bifunctor for PairBrand {
54 /// Maps functions over the values in the pair.
55 ///
56 /// This method applies one function to the first value and another to the second value.
57 ///
58 /// ### Type Signature
59 ///
60 /// `forall a b c d. Bifunctor Pair => (a -> b, c -> d, Pair a c) -> Pair b d`
61 ///
62 /// ### Type Parameters
63 ///
64 /// * `A`: The type of the first value.
65 /// * `B`: The type of the mapped first value.
66 /// * `C`: The type of the second value.
67 /// * `D`: The type of the mapped second value.
68 /// * `F`: The type of the function to apply to the first value.
69 /// * `G`: The type of the function to apply to the second value.
70 ///
71 /// ### Parameters
72 ///
73 /// * `f`: The function to apply to the first value.
74 /// * `g`: The function to apply to the second value.
75 /// * `p`: The pair to map over.
76 ///
77 /// ### Returns
78 ///
79 /// A new pair containing the mapped values.
80 ///
81 /// ### Examples
82 ///
83 /// ```
84 /// use fp_library::{brands::*, classes::bifunctor::*, functions::*, types::*};
85 ///
86 /// let x = Pair(1, 5);
87 /// assert_eq!(bimap::<PairBrand, _, _, _, _, _, _>(|a| a + 1, |b| b * 2, x), Pair(2, 10));
88 /// ```
89 fn bimap<'a, A: 'a, B: 'a, C: 'a, D: 'a, F, G>(
90 f: F,
91 g: G,
92 p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, C>),
93 ) -> Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, B, D>)
94 where
95 F: Fn(A) -> B + 'a,
96 G: Fn(C) -> D + 'a,
97 {
98 let Pair(a, c) = p;
99 Pair(f(a), g(c))
100 }
101}
102
103// PairWithFirstBrand<First> (Functor over Second)
104
105impl_kind! {
106 impl<First: 'static> for PairWithFirstBrand<First> {
107 type Of<'a, A: 'a>: 'a = Pair<First, A>;
108 }
109}
110
111impl<First: 'static> Functor for PairWithFirstBrand<First> {
112 /// Maps a function over the second value in the pair.
113 ///
114 /// This method applies a function to the second value inside the pair, producing a new pair with the transformed second value. The first value remains unchanged.
115 ///
116 /// ### Type Signature
117 ///
118 /// `forall t b a. Functor (Pair t) => (a -> b, Pair t a) -> Pair t b`
119 ///
120 /// ### Type Parameters
121 ///
122 /// * `B`: The type of the result of applying the function.
123 /// * `A`: The type of the second value.
124 /// * `F`: The type of the function to apply.
125 ///
126 /// ### Parameters
127 ///
128 /// * `f`: The function to apply to the second value.
129 /// * `fa`: The pair to map over.
130 ///
131 /// ### Returns
132 ///
133 /// A new pair containing the result of applying the function to the second value.
134 ///
135 /// ### Examples
136 ///
137 /// ```
138 /// use fp_library::{brands::*, functions::*, types::*};
139 ///
140 /// assert_eq!(map::<PairWithFirstBrand<_>, _, _, _>(|x: i32| x * 2, Pair(1, 5)), Pair(1, 10));
141 /// ```
142 fn map<'a, B: 'a, A: 'a, F>(
143 f: F,
144 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
145 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
146 where
147 F: Fn(A) -> B + 'a,
148 {
149 Pair(fa.0, f(fa.1))
150 }
151}
152
153impl<First: Clone + 'static> Lift for PairWithFirstBrand<First>
154where
155 First: Semigroup,
156{
157 /// Lifts a binary function into the pair context (over second).
158 ///
159 /// This method lifts a binary function to operate on the second values within the pair context. The first values are combined using their `Semigroup` implementation.
160 ///
161 /// ### Type Signature
162 ///
163 /// `forall t c a b. (Lift (Pair t), Semigroup t) => ((a, b) -> c, Pair t a, Pair t b) -> Pair t c`
164 ///
165 /// ### Type Parameters
166 ///
167 /// * `C`: The type of the result second value.
168 /// * `A`: The type of the first second value.
169 /// * `B`: The type of the second second value.
170 /// * `F`: The type of the binary function.
171 ///
172 /// ### Parameters
173 ///
174 /// * `f`: The binary function to apply to the second values.
175 /// * `fa`: The first pair.
176 /// * `fb`: The second pair.
177 ///
178 /// ### Returns
179 ///
180 /// A new pair where the first values are combined using `Semigroup::append` and the second values are combined using `f`.
181 ///
182 /// ### Examples
183 ///
184 /// ```
185 /// use fp_library::{brands::*, functions::*, types::*};
186 ///
187 /// assert_eq!(
188 /// lift2::<PairWithFirstBrand<String>, _, _, _, _>(|x, y| x + y, Pair("a".to_string(), 1), Pair("b".to_string(), 2)),
189 /// Pair("ab".to_string(), 3)
190 /// );
191 /// ```
192 fn lift2<'a, C, A, B, F>(
193 f: F,
194 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
195 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
196 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
197 where
198 F: Fn(A, B) -> C + 'a,
199 A: Clone + 'a,
200 B: Clone + 'a,
201 C: 'a,
202 {
203 Pair(Semigroup::append(fa.0, fb.0), f(fa.1, fb.1))
204 }
205}
206
207impl<First: Clone + 'static> Pointed for PairWithFirstBrand<First>
208where
209 First: Monoid,
210{
211 /// Wraps a value in a pair (with empty first).
212 ///
213 /// This method wraps a value in a pair, using the `Monoid::empty()` value for the first element.
214 ///
215 /// ### Type Signature
216 ///
217 /// `forall t a. (Pointed (Pair t), Monoid t) => a -> Pair t a`
218 ///
219 /// ### Type Parameters
220 ///
221 /// * `A`: The type of the value to wrap.
222 ///
223 /// ### Parameters
224 ///
225 /// * `a`: The value to wrap.
226 ///
227 /// ### Returns
228 ///
229 /// A pair containing the empty value of the first type and `a`.
230 ///
231 /// ### Examples
232 ///
233 /// ```
234 /// use fp_library::{brands::*, functions::*, types::*};
235 ///
236 /// assert_eq!(pure::<PairWithFirstBrand<String>, _>(5), Pair("".to_string(), 5));
237 /// ```
238 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
239 Pair(Monoid::empty(), a)
240 }
241}
242
243impl<First: Clone + Semigroup + 'static> ApplyFirst for PairWithFirstBrand<First> {}
244impl<First: Clone + Semigroup + 'static> ApplySecond for PairWithFirstBrand<First> {}
245
246impl<First: Clone + 'static> Semiapplicative for PairWithFirstBrand<First>
247where
248 First: Semigroup,
249{
250 /// Applies a wrapped function to a wrapped value (over second).
251 ///
252 /// This method applies a function wrapped in a pair to a value wrapped in a pair. The first values are combined using their `Semigroup` implementation.
253 ///
254 /// ### Type Signature
255 ///
256 /// `forall fn_brand t b a. (Semiapplicative (Pair t), Semigroup t) => (Pair t (fn_brand a b), Pair t a) -> Pair t b`
257 ///
258 /// ### Type Parameters
259 ///
260 /// * `FnBrand`: The brand of the cloneable function wrapper.
261 /// * `B`: The type of the output value.
262 /// * `A`: The type of the input value.
263 ///
264 /// ### Parameters
265 ///
266 /// * `ff`: The pair containing the function.
267 /// * `fa`: The pair containing the value.
268 ///
269 /// ### Returns
270 ///
271 /// A new pair where the first values are combined and the function is applied to the second value.
272 ///
273 /// ### Examples
274 ///
275 /// ```
276 /// use fp_library::{brands::*, functions::*, types::*};
277 ///
278 /// let f = Pair("a".to_string(), cloneable_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2));
279 /// assert_eq!(apply::<RcFnBrand, PairWithFirstBrand<String>, _, _>(f, Pair("b".to_string(), 5)), Pair("ab".to_string(), 10));
280 /// ```
281 fn apply<'a, FnBrand: 'a + CloneableFn, B: 'a, A: 'a + Clone>(
282 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
283 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
284 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
285 Pair(Semigroup::append(ff.0, fa.0), ff.1(fa.1))
286 }
287}
288
289impl<First: Clone + 'static> Semimonad for PairWithFirstBrand<First>
290where
291 First: Semigroup,
292{
293 /// Chains pair computations (over second).
294 ///
295 /// This method chains two computations, where the second computation depends on the result of the first. The first values are combined using their `Semigroup` implementation.
296 ///
297 /// ### Type Signature
298 ///
299 /// `forall t b a. (Semimonad (Pair t), Semigroup t) => (Pair t a, a -> Pair t b) -> Pair t b`
300 ///
301 /// ### Type Parameters
302 ///
303 /// * `B`: The type of the result of the second computation.
304 /// * `A`: The type of the result of the first computation.
305 /// * `F`: The type of the function to apply.
306 ///
307 /// ### Parameters
308 ///
309 /// * `ma`: The first pair.
310 /// * `f`: The function to apply to the second value.
311 ///
312 /// ### Returns
313 ///
314 /// A new pair where the first values are combined.
315 ///
316 /// ### Examples
317 ///
318 /// ```
319 /// use fp_library::{brands::*, functions::*, types::*};
320 ///
321 /// assert_eq!(
322 /// bind::<PairWithFirstBrand<String>, _, _, _>(Pair("a".to_string(), 5), |x| Pair("b".to_string(), x * 2)),
323 /// Pair("ab".to_string(), 10)
324 /// );
325 /// ```
326 fn bind<'a, B: 'a, A: 'a, F>(
327 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
328 f: F,
329 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
330 where
331 F: Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
332 {
333 let Pair(first, second) = ma;
334 let Pair(next_first, next_second) = f(second);
335 Pair(Semigroup::append(first, next_first), next_second)
336 }
337}
338
339impl<First: 'static> Foldable for PairWithFirstBrand<First> {
340 /// Folds the pair from the right (over second).
341 ///
342 /// This method performs a right-associative fold of the pair (over second).
343 ///
344 /// ### Type Signature
345 ///
346 /// `forall t b a. Foldable (Pair t) => ((a, b) -> b, b, Pair t a) -> b`
347 ///
348 /// ### Type Parameters
349 ///
350 /// * `FnBrand`: The brand of the cloneable function to use.
351 /// * `B`: The type of the accumulator.
352 /// * `A`: The type of the elements in the structure.
353 /// * `Func`: The type of the folding function.
354 ///
355 /// ### Parameters
356 ///
357 /// * `func`: The folding function.
358 /// * `initial`: The initial value.
359 /// * `fa`: The pair to fold.
360 ///
361 /// ### Returns
362 ///
363 /// `func(a, initial)`.
364 ///
365 /// ### Examples
366 ///
367 /// ```
368 /// use fp_library::{brands::*, functions::*, types::*};
369 ///
370 /// assert_eq!(fold_right::<RcFnBrand, PairWithFirstBrand<()>, _, _, _>(|x, acc| x + acc, 0, Pair((), 5)), 5);
371 /// ```
372 fn fold_right<'a, FnBrand, B: 'a, A: 'a, Func>(
373 func: Func,
374 initial: B,
375 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
376 ) -> B
377 where
378 Func: Fn(A, B) -> B + 'a,
379 FnBrand: CloneableFn + 'a,
380 {
381 func(fa.1, initial)
382 }
383
384 /// Folds the pair from the left (over second).
385 ///
386 /// This method performs a left-associative fold of the pair (over second).
387 ///
388 /// ### Type Signature
389 ///
390 /// `forall t b a. Foldable (Pair t) => ((b, a) -> b, b, Pair t a) -> b`
391 ///
392 /// ### Type Parameters
393 ///
394 /// * `FnBrand`: The brand of the cloneable function to use.
395 /// * `B`: The type of the accumulator.
396 /// * `A`: The type of the elements in the structure.
397 /// * `Func`: The type of the folding function.
398 ///
399 /// ### Parameters
400 ///
401 /// * `func`: The function to apply to the accumulator and each element.
402 /// * `initial`: The initial value of the accumulator.
403 /// * `fa`: The identity to fold.
404 ///
405 /// ### Returns
406 ///
407 /// `func(initial, a)`.
408 ///
409 /// ### Examples
410 ///
411 /// ```
412 /// use fp_library::{brands::*, functions::*, types::*};
413 ///
414 /// assert_eq!(fold_left::<RcFnBrand, PairWithFirstBrand<()>, _, _, _>(|acc, x| acc + x, 0, Pair((), 5)), 5);
415 /// ```
416 fn fold_left<'a, FnBrand, B: 'a, A: 'a, Func>(
417 func: Func,
418 initial: B,
419 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
420 ) -> B
421 where
422 Func: Fn(B, A) -> B + 'a,
423 FnBrand: CloneableFn + 'a,
424 {
425 func(initial, fa.1)
426 }
427
428 /// Maps the value to a monoid and returns it (over second).
429 ///
430 /// This method maps the element of the pair to a monoid and then returns it (over second).
431 ///
432 /// ### Type Signature
433 ///
434 /// `forall t m a. (Foldable (Pair t), Monoid m) => ((a) -> m, Pair t a) -> m`
435 ///
436 /// ### Type Parameters
437 ///
438 /// * `FnBrand`: The brand of the cloneable function to use.
439 /// * `M`: The type of the monoid.
440 /// * `A`: The type of the elements in the structure.
441 /// * `Func`: The type of the mapping function.
442 ///
443 /// ### Parameters
444 ///
445 /// * `func`: The mapping function.
446 /// * `fa`: The pair to fold.
447 ///
448 /// ### Returns
449 ///
450 /// `func(a)`.
451 ///
452 /// ### Examples
453 ///
454 /// ```
455 /// use fp_library::{brands::*, functions::*, types::*};
456 ///
457 /// assert_eq!(
458 /// fold_map::<RcFnBrand, PairWithFirstBrand<()>, _, _, _>(|x: i32| x.to_string(), Pair((), 5)),
459 /// "5".to_string()
460 /// );
461 /// ```
462 fn fold_map<'a, FnBrand, M, A: 'a, Func>(
463 func: Func,
464 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
465 ) -> M
466 where
467 M: Monoid + 'a,
468 Func: Fn(A) -> M + 'a,
469 FnBrand: CloneableFn + 'a,
470 {
471 func(fa.1)
472 }
473}
474
475impl<First: Clone + 'static> Traversable for PairWithFirstBrand<First> {
476 /// Traverses the pair with an applicative function (over second).
477 ///
478 /// This method maps the element of the pair to a computation, evaluates it, and combines the result into an applicative context (over second).
479 ///
480 /// ### Type Signature
481 ///
482 /// `forall t f b a. (Traversable (Pair t), Applicative f) => (a -> f b, Pair t a) -> f (Pair t b)`
483 ///
484 /// ### Type Parameters
485 ///
486 /// * `F`: The applicative context.
487 /// * `B`: The type of the elements in the resulting traversable structure.
488 /// * `A`: The type of the elements in the traversable structure.
489 /// * `Func`: The type of the function to apply.
490 ///
491 /// ### Parameters
492 ///
493 /// * `func`: The function to apply to each element, returning a value in an applicative context.
494 /// * `ta`: The pair to traverse.
495 ///
496 /// ### Returns
497 ///
498 /// The pair wrapped in the applicative context.
499 ///
500 /// ### Examples
501 ///
502 /// ```
503 /// use fp_library::{brands::*, functions::*, types::*};
504 ///
505 /// assert_eq!(
506 /// traverse::<PairWithFirstBrand<()>, OptionBrand, _, _, _>(|x| Some(x * 2), Pair((), 5)),
507 /// Some(Pair((), 10))
508 /// );
509 /// ```
510 fn traverse<'a, F: Applicative, B: 'a + Clone, A: 'a + Clone, Func>(
511 func: Func,
512 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
513 ) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)>)
514 where
515 Func: Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
516 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone,
517 {
518 let Pair(first, second) = ta;
519 F::map(move |b| Pair(first.clone(), b), func(second))
520 }
521 /// Sequences a pair of applicative (over second).
522 ///
523 /// This method evaluates the computation inside the pair and accumulates the result into an applicative context (over second).
524 ///
525 /// ### Type Signature
526 ///
527 /// `forall t f a. (Traversable (Pair t), Applicative f) => (Pair t (f a)) -> f (Pair t a)`
528 ///
529 /// ### Type Parameters
530 ///
531 /// * `F`: The applicative context.
532 /// * `A`: The type of the elements in the traversable structure.
533 ///
534 /// ### Parameters
535 ///
536 /// * `ta`: The pair containing the applicative value.
537 ///
538 /// ### Returns
539 ///
540 /// The pair wrapped in the applicative context.
541 ///
542 /// ### Examples
543 ///
544 /// ```
545 /// use fp_library::{brands::*, functions::*, types::*};
546 ///
547 /// assert_eq!(
548 /// sequence::<PairWithFirstBrand<()>, OptionBrand, _>(Pair((), Some(5))),
549 /// Some(Pair((), 5))
550 /// );
551 /// ```
552 fn sequence<'a, F: Applicative, A: 'a + Clone>(
553 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)>)
554 ) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)>)
555 where
556 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
557 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
558 {
559 let Pair(first, second) = ta;
560 F::map(move |a| Pair(first.clone(), a), second)
561 }
562}
563
564impl<First: 'static, FnBrand: SendCloneableFn> ParFoldable<FnBrand> for PairWithFirstBrand<First> {
565 /// Maps the value to a monoid and returns it in parallel (over second).
566 ///
567 /// This method maps the element of the pair to a monoid and then returns it (over second). The mapping operation may be executed in parallel.
568 ///
569 /// ### Type Signature
570 ///
571 /// `forall fn_brand t m a. (ParFoldable (Pair t), Monoid m, Send m, Sync m) => (fn_brand a m, Pair t a) -> m`
572 ///
573 /// ### Type Parameters
574 ///
575 /// * `M`: The monoid type (must be `Send + Sync`).
576 /// * `A`: The element type (must be `Send + Sync`).
577 ///
578 /// ### Parameters
579 ///
580 /// * `func`: The thread-safe function to map each element to a monoid.
581 /// * `fa`: The pair to fold.
582 ///
583 /// ### Returns
584 ///
585 /// The combined monoid value.
586 ///
587 /// ### Examples
588 ///
589 /// ```
590 /// use fp_library::{brands::*, functions::*, types::*};
591 ///
592 /// let x = Pair("a".to_string(), 1);
593 /// let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
594 /// assert_eq!(
595 /// par_fold_map::<ArcFnBrand, PairWithFirstBrand<String>, _, _>(f, x),
596 /// "1".to_string()
597 /// );
598 /// ```
599 fn par_fold_map<'a, M, A>(
600 func: <FnBrand as SendCloneableFn>::SendOf<'a, A, M>,
601 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
602 ) -> M
603 where
604 A: 'a + Clone + Send + Sync,
605 M: Monoid + Send + Sync + 'a,
606 {
607 func(fa.1)
608 }
609
610 /// Folds the pair from the right in parallel (over second).
611 ///
612 /// This method folds the pair by applying a function from right to left, potentially in parallel (over second).
613 ///
614 /// ### Type Signature
615 ///
616 /// `forall fn_brand t b a. ParFoldable (Pair t) => (fn_brand (a, b) b, b, Pair t a) -> b`
617 ///
618 /// ### Type Parameters
619 ///
620 /// * `B`: The accumulator type (must be `Send + Sync`).
621 /// * `A`: The element type (must be `Send + Sync`).
622 ///
623 /// ### Parameters
624 ///
625 /// * `func`: The thread-safe function to apply to each element and the accumulator.
626 /// * `initial`: The initial value.
627 /// * `fa`: The pair to fold.
628 ///
629 /// ### Returns
630 ///
631 /// The final accumulator value.
632 ///
633 /// ### Examples
634 ///
635 /// ```
636 /// use fp_library::{brands::*, functions::*, types::*};
637 ///
638 /// let x = Pair("a".to_string(), 1);
639 /// let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
640 /// assert_eq!(par_fold_right::<ArcFnBrand, PairWithFirstBrand<String>, _, _>(f, 10, x), 11);
641 /// ```
642 fn par_fold_right<'a, B, A>(
643 func: <FnBrand as SendCloneableFn>::SendOf<'a, (A, B), B>,
644 initial: B,
645 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
646 ) -> B
647 where
648 A: 'a + Clone + Send + Sync,
649 B: Send + Sync + 'a,
650 {
651 func((fa.1, initial))
652 }
653}
654// PairWithSecondBrand<Second> (Functor over First)
655
656impl_kind! {
657 impl<Second: 'static> for PairWithSecondBrand<Second> {
658 type Of<'a, A: 'a>: 'a = Pair<A, Second>;
659 }
660}
661
662impl<Second: 'static> Functor for PairWithSecondBrand<Second> {
663 /// Maps a function over the first value in the pair.
664 ///
665 /// This method applies a function to the first value inside the pair, producing a new pair with the transformed first value. The second value remains unchanged.
666 ///
667 /// ### Type Signature
668 ///
669 /// `forall t b a. Functor (PairWithSecond t) => (a -> b, Pair a t) -> Pair b t`
670 ///
671 /// ### Type Parameters
672 ///
673 /// * `B`: The type of the result of applying the function.
674 /// * `A`: The type of the first value.
675 /// * `F`: The type of the function to apply.
676 ///
677 /// ### Parameters
678 ///
679 /// * `f`: The function to apply to the first value.
680 /// * `fa`: The pair to map over.
681 ///
682 /// ### Returns
683 ///
684 /// A new pair containing the result of applying the function to the first value.
685 ///
686 /// ### Examples
687 ///
688 /// ```
689 /// use fp_library::{brands::*, functions::*, types::*};
690 ///
691 /// assert_eq!(map::<PairWithSecondBrand<_>, _, _, _>(|x: i32| x * 2, Pair(5, 1)), Pair(10, 1));
692 /// ```
693 fn map<'a, B: 'a, A: 'a, F>(
694 f: F,
695 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
696 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
697 where
698 F: Fn(A) -> B + 'a,
699 {
700 Pair(f(fa.0), fa.1)
701 }
702}
703
704impl<Second: Clone + 'static> Lift for PairWithSecondBrand<Second>
705where
706 Second: Semigroup,
707{
708 /// Lifts a binary function into the pair context (over first).
709 ///
710 /// This method lifts a binary function to operate on the first values within the pair context. The second values are combined using their `Semigroup` implementation.
711 ///
712 /// ### Type Signature
713 ///
714 /// `forall t c a b. (Lift (PairWithSecond t), Semigroup t) => ((a, b) -> c, Pair a t, Pair b t) -> Pair c t`
715 ///
716 /// ### Type Parameters
717 ///
718 /// * `C`: The type of the result first value.
719 /// * `A`: The type of the first first value.
720 /// * `B`: The type of the second first value.
721 /// * `F`: The type of the binary function.
722 ///
723 /// ### Parameters
724 ///
725 /// * `f`: The binary function to apply to the first values.
726 /// * `fa`: The first pair.
727 /// * `fb`: The second pair.
728 ///
729 /// ### Returns
730 ///
731 /// A new pair where the first values are combined using `f` and the second values are combined using `Semigroup::append`.
732 ///
733 /// ### Examples
734 ///
735 /// ```
736 /// use fp_library::{brands::*, functions::*, types::*};
737 ///
738 /// assert_eq!(
739 /// lift2::<PairWithSecondBrand<String>, _, _, _, _>(|x, y| x + y, Pair(1, "a".to_string()), Pair(2, "b".to_string())),
740 /// Pair(3, "ab".to_string())
741 /// );
742 /// ```
743 fn lift2<'a, C, A, B, F>(
744 f: F,
745 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
746 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
747 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
748 where
749 F: Fn(A, B) -> C + 'a,
750 A: Clone + 'a,
751 B: Clone + 'a,
752 C: 'a,
753 {
754 Pair(f(fa.0, fb.0), Semigroup::append(fa.1, fb.1))
755 }
756}
757
758impl<Second: Clone + 'static> Pointed for PairWithSecondBrand<Second>
759where
760 Second: Monoid,
761{
762 /// Wraps a value in a pair (with empty second).
763 ///
764 /// This method wraps a value in a pair, using the `Monoid::empty()` value for the second element.
765 ///
766 /// ### Type Signature
767 ///
768 /// `forall t a. (Pointed (PairWithSecond t), Monoid t) => a -> Pair a t`
769 ///
770 /// ### Type Parameters
771 ///
772 /// * `A`: The type of the value to wrap.
773 ///
774 /// ### Parameters
775 ///
776 /// * `a`: The value to wrap.
777 ///
778 /// ### Returns
779 ///
780 /// A pair containing `a` and the empty value of the second type.
781 ///
782 /// ### Examples
783 ///
784 /// ```
785 /// use fp_library::{brands::*, functions::*, types::*};
786 ///
787 /// assert_eq!(pure::<PairWithSecondBrand<String>, _>(5), Pair(5, "".to_string()));
788 /// ```
789 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
790 Pair(a, Monoid::empty())
791 }
792}
793
794impl<Second: Clone + Semigroup + 'static> ApplyFirst for PairWithSecondBrand<Second> {}
795impl<Second: Clone + Semigroup + 'static> ApplySecond for PairWithSecondBrand<Second> {}
796
797impl<Second: Clone + 'static> Semiapplicative for PairWithSecondBrand<Second>
798where
799 Second: Semigroup,
800{
801 /// Applies a wrapped function to a wrapped value (over first).
802 ///
803 /// This method applies a function wrapped in a result (as error) to a value wrapped in a result (as error).
804 ///
805 /// ### Type Signature
806 ///
807 /// `forall fn_brand t b a. (Semiapplicative (PairWithSecond t), Semigroup t) => (Pair (fn_brand a b) t, Pair a t) -> Pair b t`
808 ///
809 /// ### Type Parameters
810 ///
811 /// * `FnBrand`: The brand of the cloneable function wrapper.
812 /// * `B`: The type of the output value.
813 /// * `A`: The type of the input value.
814 ///
815 /// ### Parameters
816 ///
817 /// * `ff`: The pair containing the function (in Err).
818 /// * `fa`: The pair containing the value (in Err).
819 ///
820 /// ### Returns
821 ///
822 /// `Err(f(a))` if both are `Err`, otherwise the first success encountered.
823 ///
824 /// ### Examples
825 ///
826 /// ```
827 /// use fp_library::{brands::*, functions::*, types::*};
828 ///
829 /// let f = Pair(cloneable_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2), "a".to_string());
830 /// assert_eq!(apply::<RcFnBrand, PairWithSecondBrand<String>, _, _>(f, Pair(5, "b".to_string())), Pair(10, "ab".to_string()));
831 /// ```
832 fn apply<'a, FnBrand: 'a + CloneableFn, B: 'a, A: 'a + Clone>(
833 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
834 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
835 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
836 Pair(ff.0(fa.0), Semigroup::append(ff.1, fa.1))
837 }
838}
839
840impl<Second: Clone + 'static> Semimonad for PairWithSecondBrand<Second>
841where
842 Second: Semigroup,
843{
844 /// Chains pair computations (over first).
845 ///
846 /// This method chains two computations, where the second computation depends on the result of the first (over error).
847 ///
848 /// ### Type Signature
849 ///
850 /// `forall t b a. (Semimonad (PairWithSecond t), Semigroup t) => (Pair a t, a -> Pair b t) -> Pair b t`
851 ///
852 /// ### Type Parameters
853 ///
854 /// * `B`: The type of the result of the second computation.
855 /// * `A`: The type of the result of the first computation.
856 /// * `F`: The type of the function to apply.
857 ///
858 /// ### Parameters
859 ///
860 /// * `ma`: The first result.
861 /// * `f`: The function to apply to the error value.
862 ///
863 /// ### Returns
864 ///
865 /// The result of applying `f` to the error if `ma` is `Err`, otherwise the original success.
866 ///
867 /// ### Examples
868 ///
869 /// ```
870 /// use fp_library::{brands::*, functions::*, types::*};
871 ///
872 /// assert_eq!(
873 /// bind::<PairWithSecondBrand<String>, _, _, _>(Pair(5, "a".to_string()), |x| Pair(x * 2, "b".to_string())),
874 /// Pair(10, "ab".to_string())
875 /// );
876 /// ```
877 fn bind<'a, B: 'a, A: 'a, F>(
878 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
879 f: F,
880 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
881 where
882 F: Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
883 {
884 let Pair(first, second) = ma;
885 let Pair(next_first, next_second) = f(first);
886 Pair(next_first, Semigroup::append(second, next_second))
887 }
888}
889
890impl<Second: 'static> Foldable for PairWithSecondBrand<Second> {
891 /// Folds the pair from the right (over first).
892 ///
893 /// This method performs a right-associative fold of the result (over error).
894 ///
895 /// ### Type Signature
896 ///
897 /// `forall t b a. Foldable (PairWithSecond t) => ((a, b) -> b, b, Pair a t) -> b`
898 ///
899 /// ### Type Parameters
900 ///
901 /// * `FnBrand`: The brand of the cloneable function to use.
902 /// * `B`: The type of the accumulator.
903 /// * `A`: The type of the elements in the structure.
904 /// * `F`: The type of the folding function.
905 ///
906 /// ### Parameters
907 ///
908 /// * `func`: The folding function.
909 /// * `initial`: The initial value.
910 /// * `fa`: The result to fold.
911 ///
912 /// ### Returns
913 ///
914 /// `func(a, initial)` if `fa` is `Err(a)`, otherwise `initial`.
915 ///
916 /// ### Examples
917 ///
918 /// ```
919 /// use fp_library::{brands::*, functions::*, types::*};
920 ///
921 /// assert_eq!(fold_right::<RcFnBrand, PairWithSecondBrand<()>, _, _, _>(|x, acc| x + acc, 0, Pair(5, ())), 5);
922 /// ```
923 fn fold_right<'a, FnBrand, B: 'a, A: 'a, F>(
924 func: F,
925 initial: B,
926 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
927 ) -> B
928 where
929 F: Fn(A, B) -> B + 'a,
930 FnBrand: CloneableFn + 'a,
931 {
932 func(fa.0, initial)
933 }
934
935 /// Folds the pair from the left (over first).
936 ///
937 /// This method performs a left-associative fold of the result (over error).
938 ///
939 /// ### Type Signature
940 ///
941 /// `forall t b a. Foldable (PairWithSecond t) => ((b, a) -> b, b, Pair a t) -> b`
942 ///
943 /// ### Type Parameters
944 ///
945 /// * `FnBrand`: The brand of the cloneable function to use.
946 /// * `B`: The type of the accumulator.
947 /// * `A`: The type of the elements in the structure.
948 /// * `F`: The type of the folding function.
949 ///
950 /// ### Parameters
951 ///
952 /// * `func`: The folding function.
953 /// * `initial`: The initial value.
954 /// * `fa`: The result to fold.
955 ///
956 /// ### Returns
957 ///
958 /// `func(initial, a)` if `fa` is `Err(a)`, otherwise `initial`.
959 ///
960 /// ### Examples
961 ///
962 /// ```
963 /// use fp_library::{brands::*, functions::*, types::*};
964 ///
965 /// assert_eq!(fold_left::<RcFnBrand, PairWithSecondBrand<()>, _, _, _>(|acc, x| acc + x, 0, Pair(5, ())), 5);
966 /// ```
967 fn fold_left<'a, FnBrand, B: 'a, A: 'a, F>(
968 func: F,
969 initial: B,
970 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
971 ) -> B
972 where
973 F: Fn(B, A) -> B + 'a,
974 FnBrand: CloneableFn + 'a,
975 {
976 func(initial, fa.0)
977 }
978
979 /// Maps the value to a monoid and returns it (over first).
980 ///
981 /// This method maps the element of the result to a monoid and then returns it (over error).
982 ///
983 /// ### Type Signature
984 ///
985 /// `forall t m a. (Foldable (PairWithSecond t), Monoid m) => ((a) -> m, Pair a t) -> m`
986 ///
987 /// ### Type Parameters
988 ///
989 /// * `FnBrand`: The brand of the cloneable function to use.
990 /// * `M`: The type of the monoid.
991 /// * `A`: The type of the elements in the structure.
992 /// * `Func`: The type of the mapping function.
993 ///
994 /// ### Parameters
995 ///
996 /// * `func`: The mapping function.
997 /// * `fa`: The result to fold.
998 ///
999 /// ### Returns
1000 ///
1001 /// `func(a)` if `fa` is `Err(a)`, otherwise `M::empty()`.
1002 ///
1003 /// ### Examples
1004 ///
1005 /// ```
1006 /// use fp_library::{brands::*, functions::*, types::*};
1007 ///
1008 /// assert_eq!(
1009 /// fold_map::<RcFnBrand, PairWithSecondBrand<()>, _, _, _>(|x: i32| x.to_string(), Pair(5, ())),
1010 /// "5".to_string()
1011 /// );
1012 /// ```
1013 fn fold_map<'a, FnBrand, M, A: 'a, Func>(
1014 func: Func,
1015 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1016 ) -> M
1017 where
1018 M: Monoid + 'a,
1019 Func: Fn(A) -> M + 'a,
1020 FnBrand: CloneableFn + 'a,
1021 {
1022 func(fa.0)
1023 }
1024}
1025
1026impl<Second: Clone + 'static> Traversable for PairWithSecondBrand<Second> {
1027 /// Traverses the pair with an applicative function (over first).
1028 ///
1029 /// This method maps the element of the result to a computation, evaluates it, and combines the result into an applicative context (over error).
1030 ///
1031 /// ### Type Signature
1032 ///
1033 /// `forall t f b a. (Traversable (PairWithSecond t), Applicative f) => (a -> f b, Pair a t) -> f (Pair b t)`
1034 ///
1035 /// ### Type Parameters
1036 ///
1037 /// * `F`: The applicative context.
1038 /// * `B`: The type of the elements in the resulting traversable structure.
1039 /// * `A`: The type of the elements in the traversable structure.
1040 /// * `Func`: The type of the function to apply.
1041 ///
1042 /// ### Parameters
1043 ///
1044 /// * `func`: The function to apply.
1045 /// * `ta`: The result to traverse.
1046 ///
1047 /// ### Returns
1048 ///
1049 /// The result wrapped in the applicative context.
1050 ///
1051 /// ### Examples
1052 ///
1053 /// ```
1054 /// use fp_library::{brands::*, functions::*, types::*};
1055 ///
1056 /// assert_eq!(
1057 /// traverse::<PairWithSecondBrand<()>, OptionBrand, _, _, _>(|x| Some(x * 2), Pair(5, ())),
1058 /// Some(Pair(10, ()))
1059 /// );
1060 /// ```
1061 fn traverse<'a, F: Applicative, B: 'a + Clone, A: 'a + Clone, Func>(
1062 func: Func,
1063 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1064 ) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)>)
1065 where
1066 Func: Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1067 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone,
1068 {
1069 let Pair(first, second) = ta;
1070 F::map(move |b| Pair(b, second.clone()), func(first))
1071 }
1072
1073 /// Sequences a pair of applicative (over first).
1074 ///
1075 /// This method evaluates the computation inside the result and accumulates the result into an applicative context (over error).
1076 ///
1077 /// ### Type Signature
1078 ///
1079 /// `forall t f a. (Traversable (PairWithSecond t), Applicative f) => (Pair (f a) t) -> f (Pair a t)`
1080 ///
1081 /// ### Type Parameters
1082 ///
1083 /// * `F`: The applicative context.
1084 /// * `A`: The type of the elements in the traversable structure.
1085 ///
1086 /// ### Parameters
1087 ///
1088 /// * `ta`: The result containing the applicative value.
1089 ///
1090 /// ### Returns
1091 ///
1092 /// The result wrapped in the applicative context.
1093 ///
1094 /// ### Examples
1095 ///
1096 /// ```
1097 /// use fp_library::{brands::*, functions::*, types::*};
1098 ///
1099 /// assert_eq!(
1100 /// sequence::<PairWithSecondBrand<()>, OptionBrand, _>(Pair(Some(5), ())),
1101 /// Some(Pair(5, ()))
1102 /// );
1103 /// ```
1104 fn sequence<'a, F: Applicative, A: 'a + Clone>(
1105 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)>)
1106 ) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)>)
1107 where
1108 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
1109 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
1110 {
1111 let Pair(first, second) = ta;
1112 F::map(move |a| Pair(a, second.clone()), first)
1113 }
1114}
1115
1116impl<Second: 'static, FnBrand: SendCloneableFn> ParFoldable<FnBrand>
1117 for PairWithSecondBrand<Second>
1118{
1119 /// Maps the value to a monoid and returns it in parallel (over first).
1120 ///
1121 /// This method maps the element of the pair to a monoid and then returns it (over first). The mapping operation may be executed in parallel.
1122 ///
1123 /// ### Type Signature
1124 ///
1125 /// `forall fn_brand t m a. (ParFoldable (PairWithSecond t), Monoid m, Send m, Sync m) => (fn_brand a m, Pair a t) -> m`
1126 ///
1127 /// ### Type Parameters
1128 ///
1129 /// * `M`: The monoid type (must be `Send + Sync`).
1130 /// * `A`: The element type (must be `Send + Sync`).
1131 ///
1132 /// ### Parameters
1133 ///
1134 /// * `func`: The thread-safe function to map each element to a monoid.
1135 /// * `fa`: The pair to fold.
1136 ///
1137 /// ### Returns
1138 ///
1139 /// The combined monoid value.
1140 ///
1141 /// ### Examples
1142 ///
1143 /// ```
1144 /// use fp_library::{brands::*, functions::*, types::*};
1145 ///
1146 /// let x = Pair(1, "a".to_string());
1147 /// let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
1148 /// assert_eq!(
1149 /// par_fold_map::<ArcFnBrand, PairWithSecondBrand<String>, _, _>(f, x),
1150 /// "1".to_string()
1151 /// );
1152 /// ```
1153 fn par_fold_map<'a, M, A>(
1154 func: <FnBrand as SendCloneableFn>::SendOf<'a, A, M>,
1155 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1156 ) -> M
1157 where
1158 A: 'a + Clone + Send + Sync,
1159 M: Monoid + Send + Sync + 'a,
1160 {
1161 func(fa.0)
1162 }
1163
1164 /// Folds the pair from the right in parallel (over first).
1165 ///
1166 /// This method folds the pair by applying a function from right to left, potentially in parallel (over first).
1167 ///
1168 /// ### Type Signature
1169 ///
1170 /// `forall fn_brand t b a. ParFoldable (PairWithSecond t) => (fn_brand (a, b) b, b, Pair a t) -> b`
1171 ///
1172 /// ### Type Parameters
1173 ///
1174 /// * `B`: The accumulator type (must be `Send + Sync`).
1175 /// * `A`: The element type (must be `Send + Sync`).
1176 ///
1177 /// ### Parameters
1178 ///
1179 /// * `func`: The thread-safe function to apply to each element and the accumulator.
1180 /// * `initial`: The initial value.
1181 /// * `fa`: The pair to fold.
1182 ///
1183 /// ### Returns
1184 ///
1185 /// The final accumulator value.
1186 ///
1187 /// ### Examples
1188 ///
1189 /// ```
1190 /// use fp_library::{brands::*, functions::*, types::*};
1191 ///
1192 /// let x = Pair(1, "a".to_string());
1193 /// let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
1194 /// assert_eq!(par_fold_right::<ArcFnBrand, PairWithSecondBrand<String>, _, _>(f, 10, x), 11);
1195 /// ```
1196 fn par_fold_right<'a, B, A>(
1197 func: <FnBrand as SendCloneableFn>::SendOf<'a, (A, B), B>,
1198 initial: B,
1199 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1200 ) -> B
1201 where
1202 A: 'a + Clone + Send + Sync,
1203 B: Send + Sync + 'a,
1204 {
1205 func((fa.0, initial))
1206 }
1207}
1208
1209#[cfg(test)]
1210mod tests {
1211 use super::*;
1212 use crate::{brands::*, classes::bifunctor::*, functions::*};
1213 use quickcheck_macros::quickcheck;
1214
1215 // Bifunctor Tests
1216
1217 /// Tests `bimap` on `Pair`.
1218 #[test]
1219 fn test_bimap() {
1220 let x = Pair(1, 5);
1221 assert_eq!(bimap::<PairBrand, _, _, _, _, _, _>(|a| a + 1, |b| b * 2, x), Pair(2, 10));
1222 }
1223
1224 // Bifunctor Laws
1225
1226 /// Tests the identity law for Bifunctor.
1227 #[quickcheck]
1228 fn bifunctor_identity(
1229 first: String,
1230 second: i32,
1231 ) -> bool {
1232 let x = Pair(first, second);
1233 bimap::<PairBrand, _, _, _, _, _, _>(identity, identity, x.clone()) == x
1234 }
1235
1236 /// Tests the composition law for Bifunctor.
1237 #[quickcheck]
1238 fn bifunctor_composition(
1239 first: i32,
1240 second: i32,
1241 ) -> bool {
1242 let x = Pair(first, second);
1243 let f = |x: i32| x.wrapping_add(1);
1244 let g = |x: i32| x.wrapping_mul(2);
1245 let h = |x: i32| x.wrapping_sub(1);
1246 let i = |x: i32| if x == 0 { 0 } else { x.wrapping_div(2) };
1247
1248 bimap::<PairBrand, _, _, _, _, _, _>(compose(f, g), compose(h, i), x.clone())
1249 == bimap::<PairBrand, _, _, _, _, _, _>(
1250 f,
1251 h,
1252 bimap::<PairBrand, _, _, _, _, _, _>(g, i, x),
1253 )
1254 }
1255
1256 // Functor Laws
1257
1258 /// Tests the identity law for Functor.
1259 #[quickcheck]
1260 fn functor_identity(
1261 first: String,
1262 second: i32,
1263 ) -> bool {
1264 let x = Pair(first, second);
1265 map::<PairWithFirstBrand<String>, _, _, _>(identity, x.clone()) == x
1266 }
1267
1268 /// Tests the composition law for Functor.
1269 #[quickcheck]
1270 fn functor_composition(
1271 first: String,
1272 second: i32,
1273 ) -> bool {
1274 let x = Pair(first, second);
1275 let f = |x: i32| x.wrapping_add(1);
1276 let g = |x: i32| x.wrapping_mul(2);
1277 map::<PairWithFirstBrand<String>, _, _, _>(compose(f, g), x.clone())
1278 == map::<PairWithFirstBrand<String>, _, _, _>(
1279 f,
1280 map::<PairWithFirstBrand<String>, _, _, _>(g, x),
1281 )
1282 }
1283
1284 // Applicative Laws
1285
1286 /// Tests the identity law for Applicative.
1287 #[quickcheck]
1288 fn applicative_identity(
1289 first: String,
1290 second: i32,
1291 ) -> bool {
1292 let v = Pair(first, second);
1293 apply::<RcFnBrand, PairWithFirstBrand<String>, _, _>(
1294 pure::<PairWithFirstBrand<String>, _>(<RcFnBrand as CloneableFn>::new(identity)),
1295 v.clone(),
1296 ) == v
1297 }
1298
1299 /// Tests the homomorphism law for Applicative.
1300 #[quickcheck]
1301 fn applicative_homomorphism(x: i32) -> bool {
1302 let f = |x: i32| x.wrapping_mul(2);
1303 apply::<RcFnBrand, PairWithFirstBrand<String>, _, _>(
1304 pure::<PairWithFirstBrand<String>, _>(<RcFnBrand as CloneableFn>::new(f)),
1305 pure::<PairWithFirstBrand<String>, _>(x),
1306 ) == pure::<PairWithFirstBrand<String>, _>(f(x))
1307 }
1308
1309 /// Tests the composition law for Applicative.
1310 #[quickcheck]
1311 fn applicative_composition(
1312 w_first: String,
1313 w_second: i32,
1314 u_seed: i32,
1315 v_seed: i32,
1316 ) -> bool {
1317 let w = Pair(w_first, w_second);
1318
1319 let u_fn = <RcFnBrand as CloneableFn>::new(move |x: i32| x.wrapping_add(u_seed));
1320 let u = pure::<PairWithFirstBrand<String>, _>(u_fn);
1321
1322 let v_fn = <RcFnBrand as CloneableFn>::new(move |x: i32| x.wrapping_mul(v_seed));
1323 let v = pure::<PairWithFirstBrand<String>, _>(v_fn);
1324
1325 // RHS: u <*> (v <*> w)
1326 let vw = apply::<RcFnBrand, PairWithFirstBrand<String>, _, _>(v.clone(), w.clone());
1327 let rhs = apply::<RcFnBrand, PairWithFirstBrand<String>, _, _>(u.clone(), vw);
1328
1329 // LHS: pure(compose) <*> u <*> v <*> w
1330 let compose_fn = <RcFnBrand as CloneableFn>::new(|f: std::rc::Rc<dyn Fn(i32) -> i32>| {
1331 let f = f.clone();
1332 <RcFnBrand as CloneableFn>::new(move |g: std::rc::Rc<dyn Fn(i32) -> i32>| {
1333 let f = f.clone();
1334 let g = g.clone();
1335 <RcFnBrand as CloneableFn>::new(move |x| f(g(x)))
1336 })
1337 });
1338
1339 let pure_compose = pure::<PairWithFirstBrand<String>, _>(compose_fn);
1340 let u_applied = apply::<RcFnBrand, PairWithFirstBrand<String>, _, _>(pure_compose, u);
1341 let uv = apply::<RcFnBrand, PairWithFirstBrand<String>, _, _>(u_applied, v);
1342 let lhs = apply::<RcFnBrand, PairWithFirstBrand<String>, _, _>(uv, w);
1343
1344 lhs == rhs
1345 }
1346
1347 /// Tests the interchange law for Applicative.
1348 #[quickcheck]
1349 fn applicative_interchange(
1350 y: i32,
1351 u_seed: i32,
1352 ) -> bool {
1353 // u <*> pure y = pure ($ y) <*> u
1354 let f = move |x: i32| x.wrapping_mul(u_seed);
1355 let u = pure::<PairWithFirstBrand<String>, _>(<RcFnBrand as CloneableFn>::new(f));
1356
1357 let lhs = apply::<RcFnBrand, PairWithFirstBrand<String>, _, _>(
1358 u.clone(),
1359 pure::<PairWithFirstBrand<String>, _>(y),
1360 );
1361
1362 let rhs_fn =
1363 <RcFnBrand as CloneableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
1364 let rhs = apply::<RcFnBrand, PairWithFirstBrand<String>, _, _>(
1365 pure::<PairWithFirstBrand<String>, _>(rhs_fn),
1366 u,
1367 );
1368
1369 lhs == rhs
1370 }
1371
1372 // Monad Laws
1373
1374 /// Tests the left identity law for Monad.
1375 #[quickcheck]
1376 fn monad_left_identity(a: i32) -> bool {
1377 let f = |x: i32| Pair("f".to_string(), x.wrapping_mul(2));
1378 bind::<PairWithFirstBrand<String>, _, _, _>(pure::<PairWithFirstBrand<String>, _>(a), f)
1379 == f(a)
1380 }
1381
1382 /// Tests the right identity law for Monad.
1383 #[quickcheck]
1384 fn monad_right_identity(
1385 first: String,
1386 second: i32,
1387 ) -> bool {
1388 let m = Pair(first, second);
1389 bind::<PairWithFirstBrand<String>, _, _, _>(
1390 m.clone(),
1391 pure::<PairWithFirstBrand<String>, _>,
1392 ) == m
1393 }
1394
1395 /// Tests the associativity law for Monad.
1396 #[quickcheck]
1397 fn monad_associativity(
1398 first: String,
1399 second: i32,
1400 ) -> bool {
1401 let m = Pair(first, second);
1402 let f = |x: i32| Pair("f".to_string(), x.wrapping_mul(2));
1403 let g = |x: i32| Pair("g".to_string(), x.wrapping_add(1));
1404 bind::<PairWithFirstBrand<String>, _, _, _>(
1405 bind::<PairWithFirstBrand<String>, _, _, _>(m.clone(), f),
1406 g,
1407 ) == bind::<PairWithFirstBrand<String>, _, _, _>(m, |x| {
1408 bind::<PairWithFirstBrand<String>, _, _, _>(f(x), g)
1409 })
1410 }
1411
1412 // ParFoldable Tests for PairWithFirstBrand (Functor over Second)
1413
1414 /// Tests `par_fold_map` on `PairWithFirstBrand`.
1415 #[test]
1416 fn par_fold_map_pair_with_first() {
1417 let x = Pair("a".to_string(), 1);
1418 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
1419 assert_eq!(
1420 par_fold_map::<ArcFnBrand, PairWithFirstBrand<String>, _, _>(f, x),
1421 "1".to_string()
1422 );
1423 }
1424
1425 /// Tests `par_fold_right` on `PairWithFirstBrand`.
1426 #[test]
1427 fn par_fold_right_pair_with_first() {
1428 let x = Pair("a".to_string(), 1);
1429 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
1430 assert_eq!(par_fold_right::<ArcFnBrand, PairWithFirstBrand<String>, _, _>(f, 10, x), 11);
1431 }
1432
1433 // ParFoldable Tests for PairWithSecondBrand (Functor over First)
1434
1435 /// Tests `par_fold_map` on `PairWithSecondBrand`.
1436 #[test]
1437 fn par_fold_map_pair_with_second() {
1438 let x = Pair(1, "a".to_string());
1439 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
1440 assert_eq!(
1441 par_fold_map::<ArcFnBrand, PairWithSecondBrand<String>, _, _>(f, x),
1442 "1".to_string()
1443 );
1444 }
1445
1446 /// Tests `par_fold_right` on `PairWithSecondBrand`.
1447 #[test]
1448 fn par_fold_right_pair_with_second() {
1449 let x = Pair(1, "a".to_string());
1450 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
1451 assert_eq!(par_fold_right::<ArcFnBrand, PairWithSecondBrand<String>, _, _>(f, 10, x), 11);
1452 }
1453}