fp_library/classes/
function.rs

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