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}