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//!
6//! ### Examples
7//!
8//! ```
9//! use fp_library::{brands::*, functions::*};
10//!
11//! let f = fn_new::<RcFnBrand, _, _>(|x: i32| x * 2);
12//! assert_eq!(f(5), 10);
13//! ```
14
15use super::category::Category;
16use std::ops::Deref;
17
18/// Abstraction for wrappers over closures.
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	type Of<'a, A, B>: Deref<Target = dyn 'a + Fn(A) -> B>;
30
31	/// Creates a new function wrapper.
32	///
33	/// This function wraps the provided closure `f` into a function wrapper.
34	///
35	/// ### Type Signature
36	///
37	/// `forall a b. Function f => (a -> b) -> f a b`
38	///
39	/// ### Type Parameters
40	///
41	/// * `A`: The input type of the function.
42	/// * `B`: The output type of the function.
43	///
44	/// ### Parameters
45	///
46	/// * `f`: The closure to wrap.
47	///
48	/// ### Returns
49	///
50	/// The wrapped function.
51	///
52	/// ### Examples
53	///
54	/// ```
55	/// use fp_library::{brands::*, functions::*};
56	///
57	/// let f = fn_new::<RcFnBrand, _, _>(|x: i32| x * 2);
58	/// assert_eq!(f(5), 10);
59	/// ```
60	fn new<'a, A, B>(f: impl 'a + Fn(A) -> B) -> <Self as Function>::Of<'a, A, B>;
61}
62
63/// Creates a new function wrapper.
64///
65/// Free function version that dispatches to [the type class' associated function][`Function::new`].
66///
67/// ### Type Signature
68///
69/// `forall a b. Function f => (a -> b) -> f a b`
70///
71/// ### Type Parameters
72///
73/// * `Brand`: The brand of the function wrapper.
74/// * `A`: The input type of the function.
75/// * `B`: The output type of the function.
76///
77/// ### Parameters
78///
79/// * `f`: The closure to wrap.
80///
81/// ### Returns
82///
83/// The wrapped function.
84///
85/// ### Examples
86///
87/// ```
88/// use fp_library::{brands::*, functions::*};
89///
90/// let f = fn_new::<RcFnBrand, _, _>(|x: i32| x * 2);
91/// assert_eq!(f(5), 10);
92/// ```
93pub fn new<'a, Brand, A, B>(f: impl 'a + Fn(A) -> B) -> <Brand as Function>::Of<'a, A, B>
94where
95	Brand: Function,
96{
97	Brand::new(f)
98}