Skip to main content

fp_library/dispatch/
witherable.rs

1//! Dispatch for witherable operations:
2//! [`Witherable`](crate::classes::Witherable) and
3//! [`RefWitherable`](crate::classes::RefWitherable).
4//!
5//! Provides the following dispatch traits and unified free functions:
6//!
7//! - [`WiltDispatch`] + [`explicit::wilt`]
8//! - [`WitherDispatch`] + [`explicit::wither`]
9//!
10//! Each routes to the appropriate trait method based on the closure's argument
11//! type.
12//!
13//! ### Examples
14//!
15//! ```
16//! use fp_library::{
17//! 	brands::*,
18//! 	functions::explicit::*,
19//! 	types::*,
20//! };
21//!
22//! // wilt
23//! let y = wilt::<RcFnBrand, OptionBrand, OptionBrand, _, _, _, _, _>(
24//! 	|a: i32| Some(if a > 2 { Ok(a) } else { Err(a) }),
25//! 	Some(5),
26//! );
27//! assert_eq!(y, Some((None, Some(5))));
28//!
29//! // wither
30//! let y = wither::<RcFnBrand, OptionBrand, OptionBrand, _, _, _, _>(
31//! 	|a: i32| Some(if a > 2 { Some(a * 2) } else { None }),
32//! 	Some(5),
33//! );
34//! assert_eq!(y, Some(Some(10)));
35//! ```
36
37#[fp_macros::document_module]
38pub(crate) mod inner {
39	use {
40		crate::{
41			classes::{
42				Applicative,
43				LiftFn,
44				RefWitherable,
45				Witherable,
46			},
47			dispatch::{
48				Ref,
49				Val,
50			},
51			kinds::*,
52		},
53		fp_macros::*,
54	};
55
56	// -- WiltDispatch --
57
58	/// Trait that routes a wilt operation to the appropriate type class method.
59	///
60	/// The `Marker` type parameter is an implementation detail resolved by
61	/// the compiler from the closure's argument type; callers never specify
62	/// it directly. The `FA` type parameter is inferred from the container
63	/// argument: owned for Val dispatch, borrowed for Ref dispatch.
64	#[document_type_parameters(
65		"The lifetime of the values.",
66		"The brand of the cloneable function to use.",
67		"The brand of the witherable structure.",
68		"The applicative functor brand for the computation.",
69		"The type of the elements in the input structure.",
70		"The error type.",
71		"The success type.",
72		"The container type (owned or borrowed), inferred from the argument.",
73		"Dispatch marker type, inferred automatically. Either [`Val`](crate::dispatch::Val) or [`Ref`](crate::dispatch::Ref)."
74	)]
75	#[document_parameters("The closure implementing this dispatch.")]
76	pub trait WiltDispatch<
77		'a,
78		FnBrand,
79		Brand: Kind_cdc7cd43dac7585f,
80		M: Kind_cdc7cd43dac7585f,
81		A: 'a,
82		E: 'a,
83		O: 'a,
84		FA,
85		Marker,
86	> {
87		/// Perform the dispatched wilt operation.
88		#[document_signature]
89		///
90		#[document_parameters("The structure to partition.")]
91		///
92		#[document_returns("The partitioned result in the applicative context.")]
93		#[document_examples]
94		///
95		/// ```
96		/// use fp_library::{
97		/// 	brands::*,
98		/// 	functions::explicit::*,
99		/// 	types::*,
100		/// };
101		///
102		/// let result = wilt::<RcFnBrand, OptionBrand, OptionBrand, _, _, _, _, _>(
103		/// 	|a: i32| Some(if a > 2 { Ok(a) } else { Err(a) }),
104		/// 	Some(5),
105		/// );
106		/// assert_eq!(result, Some((None, Some(5))));
107		/// ```
108		fn dispatch(
109			self,
110			ta: FA,
111		) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
112			'a,
113			(
114				Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
115				Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
116			),
117		>);
118	}
119
120	/// Routes `Fn(A) -> M::Of<Result<O, E>>` closures to [`Witherable::wilt`].
121	#[document_type_parameters(
122		"The lifetime of the values.",
123		"The cloneable function brand (unused by Val path).",
124		"The brand of the witherable structure.",
125		"The applicative functor brand.",
126		"The type of the elements in the input structure.",
127		"The error type.",
128		"The success type.",
129		"The closure type."
130	)]
131	#[document_parameters("The closure that takes owned values.")]
132	impl<'a, FnBrand, Brand, M, A, E, O, Func>
133		WiltDispatch<
134			'a,
135			FnBrand,
136			Brand,
137			M,
138			A,
139			E,
140			O,
141			Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
142			Val,
143		> for Func
144	where
145		Brand: Witherable,
146		A: 'a + Clone,
147		E: 'a + Clone,
148		O: 'a + Clone,
149		M: Applicative,
150		Func: Fn(A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>) + 'a,
151		Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>): Clone,
152		Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>): Clone,
153	{
154		#[document_signature]
155		///
156		#[document_parameters("The structure to partition.")]
157		///
158		#[document_returns("The partitioned result in the applicative context.")]
159		#[document_examples]
160		///
161		/// ```
162		/// use fp_library::{
163		/// 	brands::*,
164		/// 	functions::explicit::*,
165		/// 	types::*,
166		/// };
167		///
168		/// let result = wilt::<RcFnBrand, OptionBrand, OptionBrand, _, _, _, _, _>(
169		/// 	|a: i32| Some(if a > 2 { Ok(a) } else { Err(a) }),
170		/// 	Some(5),
171		/// );
172		/// assert_eq!(result, Some((None, Some(5))));
173		/// ```
174		fn dispatch(
175			self,
176			ta: Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
177		) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
178			'a,
179			(
180				Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
181				Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
182			),
183		>) {
184			Brand::wilt::<M, A, E, O>(self, ta)
185		}
186	}
187
188	/// Routes `Fn(&A) -> M::Of<Result<O, E>>` closures to [`RefWitherable::ref_wilt`].
189	///
190	/// The container must be passed by reference (`&ta`).
191	#[document_type_parameters(
192		"The lifetime of the values.",
193		"The borrow lifetime.",
194		"The cloneable function brand.",
195		"The brand of the witherable structure.",
196		"The applicative functor brand.",
197		"The type of the elements in the input structure.",
198		"The error type.",
199		"The success type.",
200		"The closure type."
201	)]
202	#[document_parameters("The closure that takes references.")]
203	impl<'a, 'b, FnBrand, Brand, M, A, E, O, Func>
204		WiltDispatch<
205			'a,
206			FnBrand,
207			Brand,
208			M,
209			A,
210			E,
211			O,
212			&'b Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
213			Ref,
214		> for Func
215	where
216		Brand: RefWitherable,
217		FnBrand: LiftFn + 'a,
218		A: 'a + Clone,
219		E: 'a + Clone,
220		O: 'a + Clone,
221		M: Applicative,
222		Func: Fn(&A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>) + 'a,
223		Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>): Clone,
224		Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>): Clone,
225	{
226		#[document_signature]
227		///
228		#[document_parameters("A reference to the structure to partition.")]
229		///
230		#[document_returns("The partitioned result in the applicative context.")]
231		#[document_examples]
232		///
233		/// ```
234		/// use fp_library::{
235		/// 	brands::*,
236		/// 	functions::explicit::*,
237		/// 	types::*,
238		/// };
239		///
240		/// let v = vec![1, 2, 3, 4, 5];
241		/// let result: Option<(Vec<i32>, Vec<i32>)> =
242		/// 	wilt::<RcFnBrand, VecBrand, OptionBrand, _, _, _, _, _>(
243		/// 		|x: &i32| Some(if *x > 3 { Ok(*x) } else { Err(*x) }),
244		/// 		&v,
245		/// 	);
246		/// assert_eq!(result, Some((vec![1, 2, 3], vec![4, 5])));
247		/// ```
248		fn dispatch(
249			self,
250			ta: &'b Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
251		) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
252			'a,
253			(
254				Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
255				Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
256			),
257		>) {
258			Brand::ref_wilt::<FnBrand, M, A, E, O>(self, ta)
259		}
260	}
261
262	// -- WitherDispatch --
263
264	/// Trait that routes a wither operation to the appropriate type class method.
265	///
266	/// The `Marker` type parameter is an implementation detail resolved by
267	/// the compiler from the closure's argument type; callers never specify
268	/// it directly. The `FA` type parameter is inferred from the container
269	/// argument: owned for Val dispatch, borrowed for Ref dispatch.
270	#[document_type_parameters(
271		"The lifetime of the values.",
272		"The brand of the cloneable function to use.",
273		"The brand of the witherable structure.",
274		"The applicative functor brand for the computation.",
275		"The type of the elements in the input structure.",
276		"The type of the elements in the output structure.",
277		"The container type (owned or borrowed), inferred from the argument.",
278		"Dispatch marker type, inferred automatically. Either [`Val`](crate::dispatch::Val) or [`Ref`](crate::dispatch::Ref)."
279	)]
280	#[document_parameters("The closure implementing this dispatch.")]
281	pub trait WitherDispatch<
282		'a,
283		FnBrand,
284		Brand: Kind_cdc7cd43dac7585f,
285		M: Kind_cdc7cd43dac7585f,
286		A: 'a,
287		B: 'a,
288		FA,
289		Marker,
290	> {
291		/// Perform the dispatched wither operation.
292		#[document_signature]
293		///
294		#[document_parameters("The structure to filter.")]
295		///
296		#[document_returns("The filtered result in the applicative context.")]
297		#[document_examples]
298		///
299		/// ```
300		/// use fp_library::{
301		/// 	brands::*,
302		/// 	functions::explicit::*,
303		/// };
304		///
305		/// let result = wither::<RcFnBrand, OptionBrand, OptionBrand, _, _, _, _>(
306		/// 	|a: i32| Some(if a > 2 { Some(a * 2) } else { None }),
307		/// 	Some(5),
308		/// );
309		/// assert_eq!(result, Some(Some(10)));
310		/// ```
311		fn dispatch(
312			self,
313			ta: FA,
314		) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
315			'a,
316			Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
317		>);
318	}
319
320	/// Routes `Fn(A) -> M::Of<Option<B>>` closures to [`Witherable::wither`].
321	#[document_type_parameters(
322		"The lifetime of the values.",
323		"The cloneable function brand (unused by Val path).",
324		"The brand of the witherable structure.",
325		"The applicative functor brand.",
326		"The type of the elements in the input structure.",
327		"The type of the elements in the output structure.",
328		"The closure type."
329	)]
330	#[document_parameters("The closure that takes owned values.")]
331	impl<'a, FnBrand, Brand, M, A, B, Func>
332		WitherDispatch<
333			'a,
334			FnBrand,
335			Brand,
336			M,
337			A,
338			B,
339			Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
340			Val,
341		> for Func
342	where
343		Brand: Witherable,
344		A: 'a + Clone,
345		B: 'a + Clone,
346		M: Applicative,
347		Func: Fn(A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>) + 'a,
348		Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone,
349		Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone,
350	{
351		#[document_signature]
352		///
353		#[document_parameters("The structure to filter.")]
354		///
355		#[document_returns("The filtered result in the applicative context.")]
356		#[document_examples]
357		///
358		/// ```
359		/// use fp_library::{
360		/// 	brands::*,
361		/// 	functions::explicit::*,
362		/// };
363		///
364		/// let result = wither::<RcFnBrand, OptionBrand, OptionBrand, _, _, _, _>(
365		/// 	|a: i32| Some(if a > 2 { Some(a * 2) } else { None }),
366		/// 	Some(5),
367		/// );
368		/// assert_eq!(result, Some(Some(10)));
369		/// ```
370		fn dispatch(
371			self,
372			ta: Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
373		) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
374			'a,
375			Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
376		>) {
377			Brand::wither::<M, A, B>(self, ta)
378		}
379	}
380
381	/// Routes `Fn(&A) -> M::Of<Option<B>>` closures to [`RefWitherable::ref_wither`].
382	///
383	/// The container must be passed by reference (`&ta`).
384	#[document_type_parameters(
385		"The lifetime of the values.",
386		"The borrow lifetime.",
387		"The cloneable function brand.",
388		"The brand of the witherable structure.",
389		"The applicative functor brand.",
390		"The type of the elements in the input structure.",
391		"The type of the elements in the output structure.",
392		"The closure type."
393	)]
394	#[document_parameters("The closure that takes references.")]
395	impl<'a, 'b, FnBrand, Brand, M, A, B, Func>
396		WitherDispatch<
397			'a,
398			FnBrand,
399			Brand,
400			M,
401			A,
402			B,
403			&'b Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
404			Ref,
405		> for Func
406	where
407		Brand: RefWitherable,
408		FnBrand: LiftFn + 'a,
409		A: 'a + Clone,
410		B: 'a + Clone,
411		M: Applicative,
412		Func: Fn(&A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>) + 'a,
413		Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone,
414		Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone,
415	{
416		#[document_signature]
417		///
418		#[document_parameters("A reference to the structure to filter.")]
419		///
420		#[document_returns("The filtered result in the applicative context.")]
421		#[document_examples]
422		///
423		/// ```
424		/// use fp_library::{
425		/// 	brands::*,
426		/// 	functions::explicit::*,
427		/// };
428		///
429		/// let v = vec![1, 2, 3, 4, 5];
430		/// let result: Option<Vec<i32>> = wither::<RcFnBrand, VecBrand, OptionBrand, _, _, _, _>(
431		/// 	|x: &i32| if *x > 3 { Some(Some(*x)) } else { Some(None) },
432		/// 	&v,
433		/// );
434		/// assert_eq!(result, Some(vec![4, 5]));
435		/// ```
436		fn dispatch(
437			self,
438			ta: &'b Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
439		) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
440			'a,
441			Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
442		>) {
443			Brand::ref_wither::<FnBrand, M, A, B>(self, ta)
444		}
445	}
446
447	// -- Inference wrappers --
448
449	/// Partitions a structure based on a function returning a Result in an applicative context,
450	/// inferring the brand from the container type.
451	///
452	/// The `Brand` type parameter is inferred from the concrete type of `ta`
453	/// via [`InferableBrand`](crate::kinds::InferableBrand_cdc7cd43dac7585f). `FnBrand` and `M` (the applicative brand) must
454	/// still be specified explicitly.
455	/// Both owned and borrowed containers are supported.
456	///
457	/// For types with multiple brands, use
458	/// [`explicit::wilt`](crate::functions::explicit::wilt) with a turbofish.
459	#[document_signature]
460	///
461	#[document_type_parameters(
462		"The lifetime of the values.",
463		"The brand of the cloneable function to use (must be specified explicitly).",
464		"The container type (owned or borrowed). Brand is inferred from this.",
465		"The applicative functor brand (must be specified explicitly).",
466		"The type of the elements in the input structure.",
467		"The error type.",
468		"The success type.",
469		"Dispatch marker type, inferred automatically."
470	)]
471	///
472	#[document_parameters(
473		"The function to apply to each element, returning a Result in an applicative context.",
474		"The witherable structure (owned for Val, borrowed for Ref)."
475	)]
476	///
477	#[document_returns("The partitioned structure wrapped in the applicative context.")]
478	#[document_examples]
479	///
480	/// ```
481	/// use fp_library::{
482	/// 	brands::*,
483	/// 	functions::*,
484	/// };
485	///
486	/// let y = wilt::<RcFnBrand, _, OptionBrand, _, _, _, _>(
487	/// 	|a: i32| Some(if a > 2 { Ok(a) } else { Err(a) }),
488	/// 	Some(5),
489	/// );
490	/// assert_eq!(y, Some((None, Some(5))));
491	/// ```
492	pub fn wilt<'a, FnBrand, FA, M: Kind_cdc7cd43dac7585f, A: 'a, E: 'a, O: 'a, Marker>(
493		func: impl WiltDispatch<
494			'a,
495			FnBrand,
496			<FA as InferableBrand_cdc7cd43dac7585f>::Brand,
497			M,
498			A,
499			E,
500			O,
501			FA,
502			Marker,
503		>,
504		ta: FA,
505	) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
506		'a,
507		(
508			Apply!(<<FA as InferableBrand!(type Of<'a, A: 'a>: 'a;)>::Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
509			Apply!(<<FA as InferableBrand!(type Of<'a, A: 'a>: 'a;)>::Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
510		),
511	>)
512	where
513		FA: InferableBrand_cdc7cd43dac7585f, {
514		func.dispatch(ta)
515	}
516
517	/// Maps a function over a data structure and filters out None results in an applicative context,
518	/// inferring the brand from the container type.
519	///
520	/// The `Brand` type parameter is inferred from the concrete type of `ta`
521	/// via [`InferableBrand`](crate::kinds::InferableBrand_cdc7cd43dac7585f). `FnBrand` and `M` (the applicative brand) must
522	/// still be specified explicitly.
523	/// Both owned and borrowed containers are supported.
524	///
525	/// For types with multiple brands, use
526	/// [`explicit::wither`](crate::functions::explicit::wither) with a turbofish.
527	#[document_signature]
528	///
529	#[document_type_parameters(
530		"The lifetime of the values.",
531		"The brand of the cloneable function to use (must be specified explicitly).",
532		"The container type (owned or borrowed). Brand is inferred from this.",
533		"The applicative functor brand (must be specified explicitly).",
534		"The type of the elements in the input structure.",
535		"The type of the elements in the output structure.",
536		"Dispatch marker type, inferred automatically."
537	)]
538	///
539	#[document_parameters(
540		"The function to apply to each element, returning an Option in an applicative context.",
541		"The witherable structure (owned for Val, borrowed for Ref)."
542	)]
543	///
544	#[document_returns("The filtered structure wrapped in the applicative context.")]
545	#[document_examples]
546	///
547	/// ```
548	/// use fp_library::{
549	/// 	brands::*,
550	/// 	functions::*,
551	/// };
552	///
553	/// let y = wither::<RcFnBrand, _, OptionBrand, _, _, _>(
554	/// 	|a: i32| Some(if a > 2 { Some(a * 2) } else { None }),
555	/// 	Some(5),
556	/// );
557	/// assert_eq!(y, Some(Some(10)));
558	/// ```
559	pub fn wither<'a, FnBrand, FA, M: Kind_cdc7cd43dac7585f, A: 'a, B: 'a, Marker>(
560		func: impl WitherDispatch<
561			'a,
562			FnBrand,
563			<FA as InferableBrand_cdc7cd43dac7585f>::Brand,
564			M,
565			A,
566			B,
567			FA,
568			Marker,
569		>,
570		ta: FA,
571	) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
572		'a,
573		Apply!(<<FA as InferableBrand!(type Of<'a, A: 'a>: 'a;)>::Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
574	>)
575	where
576		FA: InferableBrand_cdc7cd43dac7585f, {
577		func.dispatch(ta)
578	}
579
580	// -- Explicit dispatch free functions --
581
582	/// Explicit dispatch functions requiring a Brand turbofish.
583	///
584	/// For most use cases, prefer the inference-enabled wrappers from
585	/// [`functions`](crate::functions).
586	pub mod explicit {
587		use super::*;
588
589		/// Partitions a structure based on a function returning a Result in an applicative context.
590		///
591		/// Dispatches to either [`Witherable::wilt`] or
592		/// [`RefWitherable::ref_wilt`] based on the closure's argument type.
593		///
594		/// The dispatch is resolved at compile time with no runtime cost.
595		#[document_signature]
596		///
597		#[document_type_parameters(
598			"The lifetime of the values.",
599			"The brand of the cloneable function to use.",
600			"The brand of the witherable structure.",
601			"The applicative functor brand for the computation.",
602			"The type of the elements in the input structure.",
603			"The error type.",
604			"The success type.",
605			"The container type (owned or borrowed), inferred from the argument.",
606			"Dispatch marker type, inferred automatically."
607		)]
608		///
609		#[document_parameters(
610			"The function to apply to each element, returning a Result in an applicative context.",
611			"The witherable structure (owned for Val, borrowed for Ref)."
612		)]
613		///
614		#[document_returns("The partitioned structure wrapped in the applicative context.")]
615		///
616		#[document_examples]
617		///
618		/// ```
619		/// use fp_library::{
620		/// 	brands::*,
621		/// 	functions::explicit::*,
622		/// 	types::*,
623		/// };
624		///
625		/// let y = wilt::<RcFnBrand, OptionBrand, OptionBrand, _, _, _, _, _>(
626		/// 	|a: i32| Some(if a > 2 { Ok(a) } else { Err(a) }),
627		/// 	Some(5),
628		/// );
629		/// assert_eq!(y, Some((None, Some(5))));
630		/// ```
631		pub fn wilt<
632			'a,
633			FnBrand,
634			Brand: Kind_cdc7cd43dac7585f,
635			M: Kind_cdc7cd43dac7585f,
636			A: 'a,
637			E: 'a,
638			O: 'a,
639			FA,
640			Marker,
641		>(
642			func: impl WiltDispatch<'a, FnBrand, Brand, M, A, E, O, FA, Marker>,
643			ta: FA,
644		) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
645			'a,
646			(
647				Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
648				Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
649			),
650		>) {
651			func.dispatch(ta)
652		}
653
654		/// Maps a function over a data structure and filters out None results in an applicative context.
655		///
656		/// Dispatches to either [`Witherable::wither`] or
657		/// [`RefWitherable::ref_wither`] based on the closure's argument type.
658		///
659		/// The dispatch is resolved at compile time with no runtime cost.
660		#[document_signature]
661		///
662		#[document_type_parameters(
663			"The lifetime of the values.",
664			"The brand of the cloneable function to use.",
665			"The brand of the witherable structure.",
666			"The applicative functor brand for the computation.",
667			"The type of the elements in the input structure.",
668			"The type of the elements in the output structure.",
669			"The container type (owned or borrowed), inferred from the argument.",
670			"Dispatch marker type, inferred automatically."
671		)]
672		///
673		#[document_parameters(
674			"The function to apply to each element, returning an Option in an applicative context.",
675			"The witherable structure (owned for Val, borrowed for Ref)."
676		)]
677		///
678		#[document_returns("The filtered structure wrapped in the applicative context.")]
679		///
680		#[document_examples]
681		///
682		/// ```
683		/// use fp_library::{
684		/// 	brands::*,
685		/// 	functions::explicit::*,
686		/// };
687		///
688		/// let y = wither::<RcFnBrand, OptionBrand, OptionBrand, _, _, _, _>(
689		/// 	|a: i32| Some(if a > 2 { Some(a * 2) } else { None }),
690		/// 	Some(5),
691		/// );
692		/// assert_eq!(y, Some(Some(10)));
693		/// ```
694		pub fn wither<
695			'a,
696			FnBrand,
697			Brand: Kind_cdc7cd43dac7585f,
698			M: Kind_cdc7cd43dac7585f,
699			A: 'a,
700			B: 'a,
701			FA,
702			Marker,
703		>(
704			func: impl WitherDispatch<'a, FnBrand, Brand, M, A, B, FA, Marker>,
705			ta: FA,
706		) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
707			'a,
708			Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
709		>) {
710			func.dispatch(ta)
711		}
712	}
713}
714
715pub use inner::*;