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