Skip to main content

fp_library/types/
tuple_1.rs

1//! Single-value tuple with [`Functor`](crate::classes::Functor), [`Applicative`](crate::classes::Applicative), [`Monad`](crate::classes::Monad), [`MonadRec`](crate::classes::MonadRec), [`Foldable`](crate::classes::Foldable), [`Traversable`](crate::classes::Traversable), and parallel folding instances.
2//!
3//! A trivial wrapper using the native Rust 1-tuple `(A,)`. The corresponding brand is [`Tuple1Brand`](crate::brands::Tuple1Brand).
4
5#[fp_macros::document_module]
6mod inner {
7	use {
8		crate::{
9			Apply,
10			brands::Tuple1Brand,
11			classes::*,
12			dispatch::Ref,
13			impl_kind,
14			kinds::*,
15		},
16		core::ops::ControlFlow,
17		fp_macros::*,
18	};
19
20	impl_kind! {
21		for Tuple1Brand {
22			type Of<A> = (A,);
23		}
24	}
25
26	impl_kind! {
27		for Tuple1Brand {
28			type Of<'a, A: 'a>: 'a = (A,);
29		}
30	}
31
32	impl Functor for Tuple1Brand {
33		/// Maps a function over the value in the tuple.
34		///
35		/// This method applies a function to the value inside the 1-tuple, producing a new 1-tuple with the transformed value.
36		#[document_signature]
37		///
38		#[document_type_parameters(
39			"The lifetime of the value.",
40			"The type of the value inside the tuple.",
41			"The type of the result of applying the function."
42		)]
43		///
44		#[document_parameters("The function to apply.", "The tuple to map over.")]
45		///
46		#[document_returns("A new 1-tuple containing the result of applying the function.")]
47		///
48		#[document_examples]
49		///
50		/// ```
51		/// use fp_library::{
52		/// 	brands::*,
53		/// 	functions::*,
54		/// };
55		///
56		/// let x = (5,);
57		/// let y = explicit::map::<Tuple1Brand, _, _, _, _>(|i| i * 2, x);
58		/// assert_eq!(y, (10,));
59		/// ```
60		fn map<'a, A: 'a, B: 'a>(
61			func: impl Fn(A) -> B + 'a,
62			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
63		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
64			(func(fa.0),)
65		}
66	}
67
68	impl Lift for Tuple1Brand {
69		/// Lifts a binary function into the tuple context.
70		///
71		/// This method lifts a binary function to operate on values within the 1-tuple context.
72		#[document_signature]
73		///
74		#[document_type_parameters(
75			"The lifetime of the values.",
76			"The type of the first tuple's value.",
77			"The type of the second tuple's value.",
78			"The return type of the function."
79		)]
80		///
81		#[document_parameters(
82			"The binary function to apply.",
83			"The first tuple.",
84			"The second tuple."
85		)]
86		///
87		#[document_returns("A new 1-tuple containing the result of applying the function.")]
88		#[document_examples]
89		///
90		/// ```
91		/// use fp_library::{
92		/// 	brands::*,
93		/// 	functions::*,
94		/// };
95		///
96		/// let x = (1,);
97		/// let y = (2,);
98		/// let z = explicit::lift2::<Tuple1Brand, _, _, _, _, _, _>(|a, b| a + b, x, y);
99		/// assert_eq!(z, (3,));
100		/// ```
101		fn lift2<'a, A, B, C>(
102			func: impl Fn(A, B) -> C + 'a,
103			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
104			fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
105		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
106		where
107			A: 'a,
108			B: 'a,
109			C: 'a, {
110			(func(fa.0, fb.0),)
111		}
112	}
113
114	impl Pointed for Tuple1Brand {
115		/// Wraps a value in a 1-tuple.
116		///
117		/// This method wraps a value in a 1-tuple context.
118		#[document_signature]
119		///
120		#[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
121		///
122		#[document_parameters("The value to wrap.")]
123		///
124		#[document_returns("A 1-tuple containing the value.")]
125		///
126		#[document_examples]
127		///
128		/// ```
129		/// use fp_library::{
130		/// 	brands::*,
131		/// 	functions::*,
132		/// };
133		///
134		/// let x = pure::<Tuple1Brand, _>(5);
135		/// assert_eq!(x, (5,));
136		/// ```
137		fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
138			(a,)
139		}
140	}
141
142	impl ApplyFirst for Tuple1Brand {}
143	impl ApplySecond for Tuple1Brand {}
144
145	impl Semiapplicative for Tuple1Brand {
146		/// Applies a wrapped function to a wrapped value.
147		///
148		/// This method applies a function wrapped in a 1-tuple to a value wrapped in a 1-tuple.
149		#[document_signature]
150		///
151		#[document_type_parameters(
152			"The lifetime of the values.",
153			"The brand of the cloneable function wrapper.",
154			"The type of the input value.",
155			"The type of the output value."
156		)]
157		///
158		#[document_parameters(
159			"The tuple containing the function.",
160			"The tuple containing the value."
161		)]
162		///
163		#[document_returns("A new 1-tuple containing the result of applying the function.")]
164		#[document_examples]
165		///
166		/// ```
167		/// use fp_library::{
168		/// 	brands::*,
169		/// 	functions::*,
170		/// };
171		///
172		/// let f = (lift_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2),);
173		/// let x = (5,);
174		/// let y = apply(f, x);
175		/// assert_eq!(y, (10,));
176		/// ```
177		fn apply<'a, FnBrand: 'a + CloneFn, A: 'a + Clone, B: 'a>(
178			ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneFn>::Of<'a, A, B>>),
179			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
180		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
181			(ff.0(fa.0),)
182		}
183	}
184
185	impl Semimonad for Tuple1Brand {
186		/// Chains 1-tuple computations.
187		///
188		/// This method chains two 1-tuple computations, where the second computation depends on the result of the first.
189		#[document_signature]
190		///
191		#[document_type_parameters(
192			"The lifetime of the values.",
193			"The type of the result of the first computation.",
194			"The type of the result of the second computation."
195		)]
196		///
197		#[document_parameters(
198			"The first tuple.",
199			"The function to apply to the value inside the tuple."
200		)]
201		///
202		#[document_returns("The result of applying `f` to the value.")]
203		#[document_examples]
204		///
205		/// ```
206		/// use fp_library::{
207		/// 	brands::*,
208		/// 	functions::*,
209		/// };
210		///
211		/// let x = (5,);
212		/// let y = explicit::bind::<Tuple1Brand, _, _, _, _>(x, |i| (i * 2,));
213		/// assert_eq!(y, (10,));
214		/// ```
215		fn bind<'a, A: 'a, B: 'a>(
216			ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
217			func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
218		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
219			func(ma.0)
220		}
221	}
222
223	impl Foldable for Tuple1Brand {
224		/// Folds the 1-tuple from the right.
225		///
226		/// This method performs a right-associative fold of the 1-tuple. Since it contains only one element, this is equivalent to applying the function to the element and the initial value.
227		#[document_signature]
228		///
229		#[document_type_parameters(
230			"The lifetime of the values.",
231			"The brand of the cloneable function to use.",
232			"The type of the elements in the structure.",
233			"The type of the accumulator."
234		)]
235		///
236		#[document_parameters(
237			"The function to apply to each element and the accumulator.",
238			"The initial value of the accumulator.",
239			"The tuple to fold."
240		)]
241		///
242		#[document_returns("The final accumulator value.")]
243		#[document_examples]
244		///
245		/// ```
246		/// use fp_library::{
247		/// 	brands::*,
248		/// 	functions::*,
249		/// };
250		///
251		/// let x = (5,);
252		/// let y = explicit::fold_right::<RcFnBrand, Tuple1Brand, _, _, _, _>(|a, b| a + b, 10, x);
253		/// assert_eq!(y, 15);
254		/// ```
255		fn fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
256			func: impl Fn(A, B) -> B + 'a,
257			initial: B,
258			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
259		) -> B
260		where
261			FnBrand: CloneFn + 'a, {
262			func(fa.0, initial)
263		}
264
265		/// Folds the 1-tuple from the left.
266		///
267		/// This method performs a left-associative fold of the 1-tuple. Since it contains only one element, this is equivalent to applying the function to the initial value and the element.
268		#[document_signature]
269		///
270		#[document_type_parameters(
271			"The lifetime of the values.",
272			"The brand of the cloneable function to use.",
273			"The type of the elements in the structure.",
274			"The type of the accumulator."
275		)]
276		///
277		#[document_parameters(
278			"The function to apply to the accumulator and each element.",
279			"The initial value of the accumulator.",
280			"The tuple to fold."
281		)]
282		///
283		#[document_returns("The final accumulator value.")]
284		#[document_examples]
285		///
286		/// ```
287		/// use fp_library::{
288		/// 	brands::*,
289		/// 	functions::*,
290		/// };
291		///
292		/// let x = (5,);
293		/// let y = explicit::fold_left::<RcFnBrand, Tuple1Brand, _, _, _, _>(|b, a| b + a, 10, x);
294		/// assert_eq!(y, 15);
295		/// ```
296		fn fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
297			func: impl Fn(B, A) -> B + 'a,
298			initial: B,
299			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
300		) -> B
301		where
302			FnBrand: CloneFn + 'a, {
303			func(initial, fa.0)
304		}
305
306		/// Maps the value to a monoid and returns it.
307		///
308		/// This method maps the element of the 1-tuple to a monoid.
309		#[document_signature]
310		///
311		#[document_type_parameters(
312			"The lifetime of the values.",
313			"The brand of the cloneable function to use.",
314			"The type of the elements in the structure.",
315			"The type of the monoid."
316		)]
317		///
318		#[document_parameters(
319			"The thread-safe function to map each element to a monoid.",
320			"The tuple to fold."
321		)]
322		///
323		#[document_returns("The monoid value.")]
324		#[document_examples]
325		///
326		/// ```
327		/// use fp_library::{
328		/// 	brands::*,
329		/// 	functions::*,
330		/// };
331		///
332		/// let x = (5,);
333		/// let y = explicit::fold_map::<RcFnBrand, Tuple1Brand, _, _, _, _>(|a: i32| a.to_string(), x);
334		/// assert_eq!(y, "5".to_string());
335		/// ```
336		fn fold_map<'a, FnBrand, A: 'a + Clone, M>(
337			func: impl Fn(A) -> M + 'a,
338			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
339		) -> M
340		where
341			M: Monoid + 'a,
342			FnBrand: CloneFn + 'a, {
343			func(fa.0)
344		}
345	}
346
347	impl Traversable for Tuple1Brand {
348		/// Traverses the 1-tuple with an applicative function.
349		///
350		/// This method maps the element of the 1-tuple to a computation, evaluates it, and wraps the result in the applicative context.
351		#[document_signature]
352		///
353		#[document_type_parameters(
354			"The lifetime of the values.",
355			"The type of the elements in the traversable structure.",
356			"The type of the elements in the resulting traversable structure.",
357			"The applicative context."
358		)]
359		///
360		#[document_parameters(
361			"The function to apply to each element, returning a value in an applicative context.",
362			"The tuple to traverse."
363		)]
364		///
365		#[document_returns("The 1-tuple wrapped in the applicative context.")]
366		#[document_examples]
367		///
368		/// ```
369		/// use fp_library::{
370		/// 	brands::*,
371		/// 	functions::*,
372		/// };
373		///
374		/// let x = (5,);
375		/// let y =
376		/// 	explicit::traverse::<RcFnBrand, Tuple1Brand, _, _, OptionBrand, _, _>(|a| Some(a * 2), x);
377		/// assert_eq!(y, Some((10,)));
378		/// ```
379		fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
380			func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
381			ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
382		) -> 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>)>)
383		where
384			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
385			F::map(|b| (b,), func(ta.0))
386		}
387
388		/// Sequences a 1-tuple of applicative.
389		///
390		/// This method evaluates the computation inside the 1-tuple and wraps the result in the applicative context.
391		#[document_signature]
392		///
393		#[document_type_parameters(
394			"The lifetime of the values.",
395			"The type of the elements in the traversable structure.",
396			"The applicative context."
397		)]
398		///
399		#[document_parameters("The tuple containing the applicative value.")]
400		///
401		#[document_returns("The 1-tuple wrapped in the applicative context.")]
402		///
403		#[document_examples]
404		///
405		/// ```
406		/// use fp_library::{
407		/// 	brands::*,
408		/// 	functions::*,
409		/// };
410		///
411		/// let x = (Some(5),);
412		/// let y = sequence::<Tuple1Brand, _, OptionBrand>(x);
413		/// assert_eq!(y, Some((5,)));
414		/// ```
415		fn sequence<'a, A: 'a + Clone, F: Applicative>(
416			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>)>)
417		) -> 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>)>)
418		where
419			Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
420			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
421			F::map(|a| (a,), ta.0)
422		}
423	}
424
425	// -- By-reference trait implementations --
426
427	impl RefFunctor for Tuple1Brand {
428		/// Maps a function over the 1-tuple by reference.
429		#[document_signature]
430		#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
431		#[document_parameters("The function.", "The tuple.")]
432		#[document_returns("A new 1-tuple containing the result.")]
433		#[document_examples]
434		///
435		/// ```
436		/// use fp_library::{
437		/// 	brands::*,
438		/// 	functions::*,
439		/// };
440		/// assert_eq!(explicit::map::<Tuple1Brand, _, _, _, _>(|x: &i32| *x * 2, &(5,)), (10,));
441		/// ```
442		fn ref_map<'a, A: 'a, B: 'a>(
443			func: impl Fn(&A) -> B + 'a,
444			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
445		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
446			(func(&fa.0),)
447		}
448	}
449
450	impl RefFoldable for Tuple1Brand {
451		/// Folds the 1-tuple by reference.
452		#[document_signature]
453		#[document_type_parameters(
454			"The lifetime.",
455			"The brand.",
456			"The element type.",
457			"The monoid type."
458		)]
459		#[document_parameters("The mapping function.", "The tuple.")]
460		#[document_returns("The monoid value.")]
461		#[document_examples]
462		///
463		/// ```
464		/// use fp_library::{
465		/// 	brands::*,
466		/// 	functions::*,
467		/// };
468		/// let result =
469		/// 	explicit::fold_map::<RcFnBrand, Tuple1Brand, _, _, _, _>(|x: &i32| x.to_string(), &(5,));
470		/// assert_eq!(result, "5");
471		/// ```
472		fn ref_fold_map<'a, FnBrand, A: 'a + Clone, M>(
473			func: impl Fn(&A) -> M + 'a,
474			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
475		) -> M
476		where
477			FnBrand: LiftFn + 'a,
478			M: Monoid + 'a, {
479			func(&fa.0)
480		}
481	}
482
483	impl RefTraversable for Tuple1Brand {
484		/// Traverses the 1-tuple by reference.
485		#[document_signature]
486		#[document_type_parameters(
487			"The lifetime.",
488			"The brand.",
489			"The input type.",
490			"The output type.",
491			"The applicative."
492		)]
493		#[document_parameters("The function.", "The tuple.")]
494		#[document_returns("The traversed result.")]
495		#[document_examples]
496		///
497		/// ```
498		/// use fp_library::{
499		/// 	brands::*,
500		/// 	functions::*,
501		/// };
502		/// let result: Option<(String,)> = ref_traverse::<Tuple1Brand, RcFnBrand, _, _, OptionBrand>(
503		/// 	|x: &i32| Some(x.to_string()),
504		/// 	&(42,),
505		/// );
506		/// assert_eq!(result, Some(("42".to_string(),)));
507		/// ```
508		fn ref_traverse<'a, FnBrand, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
509			func: impl Fn(&A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
510			ta: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
511		) -> 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>)>)
512		where
513			FnBrand: LiftFn + 'a,
514			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone,
515			Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
516			F::map(|b| (b,), func(&ta.0))
517		}
518	}
519
520	impl RefPointed for Tuple1Brand {
521		/// Creates a 1-tuple from a reference by cloning.
522		#[document_signature]
523		#[document_type_parameters("The lifetime.", "The value type.")]
524		#[document_parameters("The reference to wrap.")]
525		#[document_returns("A 1-tuple containing a clone of the value.")]
526		#[document_examples]
527		///
528		/// ```
529		/// use fp_library::{
530		/// 	brands::*,
531		/// 	functions::*,
532		/// };
533		///
534		/// let x = 42;
535		/// let result: (i32,) = ref_pure::<Tuple1Brand, _>(&x);
536		/// assert_eq!(result, (42,));
537		/// ```
538		fn ref_pure<'a, A: Clone + 'a>(
539			a: &A
540		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
541			(a.clone(),)
542		}
543	}
544
545	impl RefLift for Tuple1Brand {
546		/// Combines two 1-tuples with a by-reference binary function.
547		#[document_signature]
548		#[document_type_parameters("The lifetime.", "First input.", "Second input.", "Output.")]
549		#[document_parameters("The binary function.", "The first tuple.", "The second tuple.")]
550		#[document_returns("The combined 1-tuple.")]
551		#[document_examples]
552		///
553		/// ```
554		/// use fp_library::{
555		/// 	brands::*,
556		/// 	functions::*,
557		/// };
558		///
559		/// let result =
560		/// 	explicit::lift2::<Tuple1Brand, _, _, _, _, _, _>(|a: &i32, b: &i32| *a + *b, &(1,), &(2,));
561		/// assert_eq!(result, (3,));
562		/// ```
563		fn ref_lift2<'a, A: 'a, B: 'a, C: 'a>(
564			func: impl Fn(&A, &B) -> C + 'a,
565			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
566			fb: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
567		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>) {
568			(func(&fa.0, &fb.0),)
569		}
570	}
571
572	impl RefSemiapplicative for Tuple1Brand {
573		/// Applies a wrapped by-ref function within a 1-tuple.
574		#[document_signature]
575		#[document_type_parameters(
576			"The lifetime.",
577			"The function brand.",
578			"The input type.",
579			"The output type."
580		)]
581		#[document_parameters(
582			"The tuple containing the function.",
583			"The tuple containing the value."
584		)]
585		#[document_returns("A 1-tuple containing the result.")]
586		#[document_examples]
587		///
588		/// ```
589		/// use fp_library::{
590		/// 	brands::*,
591		/// 	classes::*,
592		/// 	functions::*,
593		/// };
594		///
595		/// let f: std::rc::Rc<dyn Fn(&i32) -> i32> = std::rc::Rc::new(|x: &i32| *x + 1);
596		/// let result = ref_apply::<RcFnBrand, Tuple1Brand, _, _>(&(f,), &(5,));
597		/// assert_eq!(result, (6,));
598		/// ```
599		fn ref_apply<'a, FnBrand: 'a + CloneFn<Ref>, A: 'a, B: 'a>(
600			ff: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneFn<Ref>>::Of<'a, A, B>>),
601			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
602		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
603			((*ff.0)(&fa.0),)
604		}
605	}
606
607	impl RefSemimonad for Tuple1Brand {
608		/// Chains 1-tuple computations by reference.
609		#[document_signature]
610		#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
611		#[document_parameters("The input tuple.", "The function to apply by reference.")]
612		#[document_returns("The resulting 1-tuple.")]
613		#[document_examples]
614		///
615		/// ```
616		/// use fp_library::{
617		/// 	brands::*,
618		/// 	functions::*,
619		/// };
620		///
621		/// let result: (String,) =
622		/// 	explicit::bind::<Tuple1Brand, _, _, _, _>(&(42,), |x: &i32| (x.to_string(),));
623		/// assert_eq!(result, ("42".to_string(),));
624		/// ```
625		fn ref_bind<'a, A: 'a, B: 'a>(
626			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
627			f: impl Fn(&A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
628		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
629			f(&fa.0)
630		}
631	}
632
633	impl MonadRec for Tuple1Brand {
634		/// Performs tail-recursive monadic computation over 1-tuples.
635		///
636		/// Since the 1-tuple has no effect, this simply loops on the inner value
637		/// until the step function returns [`ControlFlow::Break`].
638		#[document_signature]
639		///
640		#[document_type_parameters(
641			"The lifetime of the computation.",
642			"The type of the initial value and loop state.",
643			"The type of the result."
644		)]
645		///
646		#[document_parameters("The step function.", "The initial value.")]
647		///
648		#[document_returns("A 1-tuple containing the result of the computation.")]
649		///
650		#[document_examples]
651		///
652		/// ```
653		/// use {
654		/// 	core::ops::ControlFlow,
655		/// 	fp_library::{
656		/// 		brands::*,
657		/// 		functions::*,
658		/// 		types::*,
659		/// 	},
660		/// };
661		///
662		/// let result = tail_rec_m::<Tuple1Brand, _, _>(
663		/// 	|n| {
664		/// 		if n < 10 { (ControlFlow::Continue(n + 1),) } else { (ControlFlow::Break(n),) }
665		/// 	},
666		/// 	0,
667		/// );
668		/// assert_eq!(result, (10,));
669		/// ```
670		fn tail_rec_m<'a, A: 'a, B: 'a>(
671			func: impl Fn(
672				A,
673			)
674				-> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, ControlFlow<B, A>>)
675			+ 'a,
676			initial: A,
677		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
678			let mut current = initial;
679			loop {
680				match func(current).0 {
681					ControlFlow::Continue(next) => current = next,
682					ControlFlow::Break(b) => return (b,),
683				}
684			}
685		}
686	}
687}
688
689#[cfg(test)]
690mod tests {
691
692	use {
693		crate::{
694			brands::*,
695			classes::*,
696			functions::*,
697		},
698		quickcheck_macros::quickcheck,
699	};
700
701	// Functor Laws
702
703	/// Tests the identity law for Functor.
704	#[quickcheck]
705	fn functor_identity(x: i32) -> bool {
706		let x = (x,);
707		explicit::map::<Tuple1Brand, _, _, _, _>(identity, x) == x
708	}
709
710	/// Tests the composition law for Functor.
711	#[quickcheck]
712	fn functor_composition(x: i32) -> bool {
713		let x = (x,);
714		let f = |x: i32| x.wrapping_add(1);
715		let g = |x: i32| x.wrapping_mul(2);
716		explicit::map::<Tuple1Brand, _, _, _, _>(compose(f, g), x)
717			== explicit::map::<Tuple1Brand, _, _, _, _>(
718				f,
719				explicit::map::<Tuple1Brand, _, _, _, _>(g, x),
720			)
721	}
722
723	// Applicative Laws
724
725	/// Tests the identity law for Applicative.
726	#[quickcheck]
727	fn applicative_identity(v: i32) -> bool {
728		let v = (v,);
729		apply(pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(identity)), v) == v
730	}
731
732	/// Tests the homomorphism law for Applicative.
733	#[quickcheck]
734	fn applicative_homomorphism(x: i32) -> bool {
735		let f = |x: i32| x.wrapping_mul(2);
736		apply(pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(f)), pure::<Tuple1Brand, _>(x))
737			== pure::<Tuple1Brand, _>(f(x))
738	}
739
740	/// Tests the composition law for Applicative.
741	#[quickcheck]
742	fn applicative_composition(
743		w: i32,
744		u_val: i32,
745		v_val: i32,
746	) -> bool {
747		let w = (w,);
748		let v_fn = move |x: i32| x.wrapping_mul(v_val);
749		let u_fn = move |x: i32| x.wrapping_add(u_val);
750
751		let v = pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(v_fn));
752		let u = pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(u_fn));
753
754		// RHS: u <*> (v <*> w)
755		let vw = apply(v.clone(), w);
756		let rhs = apply(u.clone(), vw);
757
758		// LHS: pure(compose) <*> u <*> v <*> w
759		let composed = move |x| u_fn(v_fn(x));
760		let uv = pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(composed));
761
762		let lhs = apply(uv, w);
763
764		lhs == rhs
765	}
766
767	/// Tests the interchange law for Applicative.
768	#[quickcheck]
769	fn applicative_interchange(y: i32) -> bool {
770		// u <*> pure y = pure ($ y) <*> u
771		let f = |x: i32| x.wrapping_mul(2);
772		let u = pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(f));
773
774		let lhs = apply(u.clone(), pure::<Tuple1Brand, _>(y));
775
776		let rhs_fn = <RcFnBrand as LiftFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
777		let rhs = apply(pure::<Tuple1Brand, _>(rhs_fn), u);
778
779		lhs == rhs
780	}
781
782	// Monad Laws
783
784	/// Tests the left identity law for Monad.
785	#[quickcheck]
786	fn monad_left_identity(a: i32) -> bool {
787		let f = |x: i32| (x.wrapping_mul(2),);
788		explicit::bind::<Tuple1Brand, _, _, _, _>(pure::<Tuple1Brand, _>(a), f) == f(a)
789	}
790
791	/// Tests the right identity law for Monad.
792	#[quickcheck]
793	fn monad_right_identity(m: i32) -> bool {
794		let m = (m,);
795		explicit::bind::<Tuple1Brand, _, _, _, _>(m, pure::<Tuple1Brand, _>) == m
796	}
797
798	/// Tests the associativity law for Monad.
799	#[quickcheck]
800	fn monad_associativity(m: i32) -> bool {
801		let m = (m,);
802		let f = |x: i32| (x.wrapping_mul(2),);
803		let g = |x: i32| (x.wrapping_add(1),);
804		explicit::bind::<Tuple1Brand, _, _, _, _>(
805			explicit::bind::<Tuple1Brand, _, _, _, _>(m, f),
806			g,
807		) == explicit::bind::<Tuple1Brand, _, _, _, _>(m, |x| {
808			explicit::bind::<Tuple1Brand, _, _, _, _>(f(x), g)
809		})
810	}
811
812	// Edge Cases
813
814	/// Tests the `map` function.
815	#[test]
816	fn map_test() {
817		assert_eq!(explicit::map::<Tuple1Brand, _, _, _, _>(|x: i32| x + 1, (1,)), (2,));
818	}
819
820	/// Tests the `bind` function.
821	#[test]
822	fn bind_test() {
823		assert_eq!(explicit::bind::<Tuple1Brand, _, _, _, _>((1,), |x| (x + 1,)), (2,));
824	}
825
826	/// Tests the `fold_right` function.
827	#[test]
828	fn fold_right_test() {
829		assert_eq!(
830			crate::functions::explicit::fold_right::<RcFnBrand, Tuple1Brand, _, _, _, _>(
831				|x: i32, acc| x + acc,
832				0,
833				(1,)
834			),
835			1
836		);
837	}
838
839	/// Tests the `fold_left` function.
840	#[test]
841	fn fold_left_test() {
842		assert_eq!(
843			crate::functions::explicit::fold_left::<RcFnBrand, Tuple1Brand, _, _, _, _>(
844				|acc, x: i32| acc + x,
845				0,
846				(1,)
847			),
848			1
849		);
850	}
851
852	/// Tests the `traverse` function.
853	#[test]
854	fn traverse_test() {
855		assert_eq!(
856			crate::classes::traversable::traverse::<Tuple1Brand, _, _, OptionBrand>(
857				|x: i32| Some(x + 1),
858				(1,)
859			),
860			Some((2,))
861		);
862	}
863
864	// MonadRec tests
865
866	/// Tests the MonadRec identity law: `tail_rec_m(|a| pure(Done(a)), x) == pure(x)`.
867	#[quickcheck]
868	fn monad_rec_identity(x: i32) -> bool {
869		use {
870			crate::classes::monad_rec::tail_rec_m,
871			core::ops::ControlFlow,
872		};
873		tail_rec_m::<Tuple1Brand, _, _>(|a| (ControlFlow::Break(a),), x) == (x,)
874	}
875
876	/// Tests a recursive computation that sums a range via `tail_rec_m`.
877	#[test]
878	fn monad_rec_sum_range() {
879		use {
880			crate::classes::monad_rec::tail_rec_m,
881			core::ops::ControlFlow,
882		};
883		let result = tail_rec_m::<Tuple1Brand, _, _>(
884			|(n, acc)| {
885				if n == 0 {
886					(ControlFlow::Break(acc),)
887				} else {
888					(ControlFlow::Continue((n - 1, acc + n)),)
889				}
890			},
891			(100i64, 0i64),
892		);
893		assert_eq!(result, (5050,));
894	}
895
896	/// Tests stack safety: `tail_rec_m` handles large iteration counts.
897	#[test]
898	fn monad_rec_stack_safety() {
899		use {
900			crate::classes::monad_rec::tail_rec_m,
901			core::ops::ControlFlow,
902		};
903		let iterations: i64 = 200_000;
904		let result = tail_rec_m::<Tuple1Brand, _, _>(
905			|acc| {
906				if acc < iterations {
907					(ControlFlow::Continue(acc + 1),)
908				} else {
909					(ControlFlow::Break(acc),)
910				}
911			},
912			0i64,
913		);
914		assert_eq!(result, (iterations,));
915	}
916}