Skip to main content

fp_library/classes/
function.rs

1//! Wrappers over closures for generic handling of functions in higher-kinded contexts.
2//!
3//! ### Examples
4//!
5//! ```
6//! use fp_library::{brands::*, functions::*};
7//!
8//! let f = fn_new::<RcFnBrand, _, _>(|x: i32| x * 2);
9//! assert_eq!(f(5), 10);
10//! ```
11
12use super::category::Category;
13use fp_macros::doc_params;
14use fp_macros::doc_type_params;
15use fp_macros::hm_signature;
16use std::ops::Deref;
17
18/// A trait for wrappers over closures, allowing for generic handling of functions in higher-kinded contexts.
19///
20/// This trait is implemented by "Brand" types (like [`ArcFnBrand`][crate::brands::ArcFnBrand]
21/// and [`RcFnBrand`][crate::brands::RcFnBrand]) to provide a way to construct
22/// and type-check wrappers over closures (`Arc<dyn Fn...>`, `Rc<dyn Fn...>`,
23/// etc.) in a generic context, allowing library users to choose between
24/// implementations at function call sites.
25///
26/// The lifetime `'a` ensures the function doesn't outlive referenced data,
27/// while generic types `A` and `B` represent the input and output types, respectively.
28pub trait Function: Category {
29	/// The type of the function wrapper.
30	///
31	/// This associated type represents the concrete type of the wrapper (e.g., `Rc<dyn Fn(A) -> B>`)
32	/// that dereferences to the underlying closure.
33	type Of<'a, A, B>: Deref<Target = dyn 'a + Fn(A) -> B>;
34
35	/// Creates a new function wrapper.
36	///
37	/// This function wraps the provided closure `f` into a function wrapper.
38	///
39	/// ### Type Signature
40	///
41	#[hm_signature(Function)]
42	///
43	/// ### Type Parameters
44	///
45	#[doc_type_params(
46		"The lifetime of the function and its captured data.",
47		"The input type of the function.",
48		"The output type of the function."
49	)]
50	///
51	/// ### Parameters
52	///
53	#[doc_params("The closure to wrap.", "The input value to the function.")]
54	/// ### Returns
55	///
56	/// The wrapped function.
57	///
58	/// ### Examples
59	///
60	/// ```
61	/// use fp_library::{brands::*, functions::*};
62	///
63	/// let f = fn_new::<RcFnBrand, _, _>(|x: i32| x * 2);
64	/// assert_eq!(f(5), 10);
65	/// ```
66	fn new<'a, A, B>(f: impl 'a + Fn(A) -> B) -> <Self as Function>::Of<'a, A, B>;
67}
68
69/// Creates a new function wrapper.
70///
71/// Free function version that dispatches to [the type class' associated function][`Function::new`].
72///
73/// ### Type Signature
74///
75#[hm_signature(Function)]
76///
77/// ### Type Parameters
78///
79#[doc_type_params(
80	"The lifetime of the function and its captured data.",
81	"The brand of the function wrapper.",
82	"The input type of the function.",
83	"The output type of the function."
84)]
85///
86/// ### Parameters
87///
88#[doc_params("The closure to wrap.", "The input value to the function.")]
89/// ### Returns
90///
91/// The wrapped function.
92///
93/// ### Examples
94///
95/// ```
96/// use fp_library::{brands::*, functions::*};
97///
98/// let f = fn_new::<RcFnBrand, _, _>(|x: i32| x * 2);
99/// assert_eq!(f(5), 10);
100/// ```
101pub fn new<'a, Brand, A, B>(f: impl 'a + Fn(A) -> B) -> <Brand as Function>::Of<'a, A, B>
102where
103	Brand: Function,
104{
105	Brand::new(f)
106}