fp_library/classes/
function.rs

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