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,)`.
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::<RcFnBrand, Tuple1Brand, _, _>(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::<RcFnBrand, Tuple1Brand, _, _>(
730			pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(identity)),
731			v,
732		) == v
733	}
734
735	/// Tests the homomorphism law for Applicative.
736	#[quickcheck]
737	fn applicative_homomorphism(x: i32) -> bool {
738		let f = |x: i32| x.wrapping_mul(2);
739		apply::<RcFnBrand, Tuple1Brand, _, _>(
740			pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(f)),
741			pure::<Tuple1Brand, _>(x),
742		) == pure::<Tuple1Brand, _>(f(x))
743	}
744
745	/// Tests the composition law for Applicative.
746	#[quickcheck]
747	fn applicative_composition(
748		w: i32,
749		u_val: i32,
750		v_val: i32,
751	) -> bool {
752		let w = (w,);
753		let v_fn = move |x: i32| x.wrapping_mul(v_val);
754		let u_fn = move |x: i32| x.wrapping_add(u_val);
755
756		let v = pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(v_fn));
757		let u = pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(u_fn));
758
759		// RHS: u <*> (v <*> w)
760		let vw = apply::<RcFnBrand, Tuple1Brand, _, _>(v.clone(), w);
761		let rhs = apply::<RcFnBrand, Tuple1Brand, _, _>(u.clone(), vw);
762
763		// LHS: pure(compose) <*> u <*> v <*> w
764		let composed = move |x| u_fn(v_fn(x));
765		let uv = pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(composed));
766
767		let lhs = apply::<RcFnBrand, Tuple1Brand, _, _>(uv, w);
768
769		lhs == rhs
770	}
771
772	/// Tests the interchange law for Applicative.
773	#[quickcheck]
774	fn applicative_interchange(y: i32) -> bool {
775		// u <*> pure y = pure ($ y) <*> u
776		let f = |x: i32| x.wrapping_mul(2);
777		let u = pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(f));
778
779		let lhs = apply::<RcFnBrand, Tuple1Brand, _, _>(u.clone(), pure::<Tuple1Brand, _>(y));
780
781		let rhs_fn = <RcFnBrand as LiftFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
782		let rhs = apply::<RcFnBrand, Tuple1Brand, _, _>(pure::<Tuple1Brand, _>(rhs_fn), u);
783
784		lhs == rhs
785	}
786
787	// Monad Laws
788
789	/// Tests the left identity law for Monad.
790	#[quickcheck]
791	fn monad_left_identity(a: i32) -> bool {
792		let f = |x: i32| (x.wrapping_mul(2),);
793		explicit::bind::<Tuple1Brand, _, _, _, _>(pure::<Tuple1Brand, _>(a), f) == f(a)
794	}
795
796	/// Tests the right identity law for Monad.
797	#[quickcheck]
798	fn monad_right_identity(m: i32) -> bool {
799		let m = (m,);
800		explicit::bind::<Tuple1Brand, _, _, _, _>(m, pure::<Tuple1Brand, _>) == m
801	}
802
803	/// Tests the associativity law for Monad.
804	#[quickcheck]
805	fn monad_associativity(m: i32) -> bool {
806		let m = (m,);
807		let f = |x: i32| (x.wrapping_mul(2),);
808		let g = |x: i32| (x.wrapping_add(1),);
809		explicit::bind::<Tuple1Brand, _, _, _, _>(
810			explicit::bind::<Tuple1Brand, _, _, _, _>(m, f),
811			g,
812		) == explicit::bind::<Tuple1Brand, _, _, _, _>(m, |x| {
813			explicit::bind::<Tuple1Brand, _, _, _, _>(f(x), g)
814		})
815	}
816
817	// Edge Cases
818
819	/// Tests the `map` function.
820	#[test]
821	fn map_test() {
822		assert_eq!(explicit::map::<Tuple1Brand, _, _, _, _>(|x: i32| x + 1, (1,)), (2,));
823	}
824
825	/// Tests the `bind` function.
826	#[test]
827	fn bind_test() {
828		assert_eq!(explicit::bind::<Tuple1Brand, _, _, _, _>((1,), |x| (x + 1,)), (2,));
829	}
830
831	/// Tests the `fold_right` function.
832	#[test]
833	fn fold_right_test() {
834		assert_eq!(
835			crate::functions::explicit::fold_right::<RcFnBrand, Tuple1Brand, _, _, _, _>(
836				|x: i32, acc| x + acc,
837				0,
838				(1,)
839			),
840			1
841		);
842	}
843
844	/// Tests the `fold_left` function.
845	#[test]
846	fn fold_left_test() {
847		assert_eq!(
848			crate::functions::explicit::fold_left::<RcFnBrand, Tuple1Brand, _, _, _, _>(
849				|acc, x: i32| acc + x,
850				0,
851				(1,)
852			),
853			1
854		);
855	}
856
857	/// Tests the `traverse` function.
858	#[test]
859	fn traverse_test() {
860		assert_eq!(
861			crate::classes::traversable::traverse::<Tuple1Brand, _, _, OptionBrand>(
862				|x: i32| Some(x + 1),
863				(1,)
864			),
865			Some((2,))
866		);
867	}
868
869	// MonadRec tests
870
871	/// Tests the MonadRec identity law: `tail_rec_m(|a| pure(Done(a)), x) == pure(x)`.
872	#[quickcheck]
873	fn monad_rec_identity(x: i32) -> bool {
874		use {
875			crate::classes::monad_rec::tail_rec_m,
876			core::ops::ControlFlow,
877		};
878		tail_rec_m::<Tuple1Brand, _, _>(|a| (ControlFlow::Break(a),), x) == (x,)
879	}
880
881	/// Tests a recursive computation that sums a range via `tail_rec_m`.
882	#[test]
883	fn monad_rec_sum_range() {
884		use {
885			crate::classes::monad_rec::tail_rec_m,
886			core::ops::ControlFlow,
887		};
888		let result = tail_rec_m::<Tuple1Brand, _, _>(
889			|(n, acc)| {
890				if n == 0 {
891					(ControlFlow::Break(acc),)
892				} else {
893					(ControlFlow::Continue((n - 1, acc + n)),)
894				}
895			},
896			(100i64, 0i64),
897		);
898		assert_eq!(result, (5050,));
899	}
900
901	/// Tests stack safety: `tail_rec_m` handles large iteration counts.
902	#[test]
903	fn monad_rec_stack_safety() {
904		use {
905			crate::classes::monad_rec::tail_rec_m,
906			core::ops::ControlFlow,
907		};
908		let iterations: i64 = 200_000;
909		let result = tail_rec_m::<Tuple1Brand, _, _>(
910			|acc| {
911				if acc < iterations {
912					(ControlFlow::Continue(acc + 1),)
913				} else {
914					(ControlFlow::Break(acc),)
915				}
916			},
917			0i64,
918		);
919		assert_eq!(result, (iterations,));
920	}
921}