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}