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}