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