fp_library/classes/arrow.rs
1//! Composable function wrappers with [`Category`](crate::classes::Category) and [`Strong`](crate::classes::profunctor::Strong) instances.
2//!
3//! The [`Arrow`] trait provides composable, callable wrappers over closures.
4//! It extends [`Category`](crate::classes::Category) and [`Strong`](crate::classes::profunctor::Strong),
5//! aligning with Haskell's `Arrow` type class.
6//!
7//! ### Examples
8//!
9//! ```
10//! use fp_library::{
11//! brands::*,
12//! functions::*,
13//! };
14//!
15//! let f = arrow::<RcFnBrand, _, _>(|x: i32| x * 2);
16//! assert_eq!(f(5), 10);
17//! ```
18
19#[fp_macros::document_module]
20mod inner {
21 use {
22 crate::classes::{
23 profunctor::*,
24 *,
25 },
26 fp_macros::*,
27 std::ops::Deref,
28 };
29
30 /// A trait for composable function wrappers with [`Category`](crate::classes::Category) and [`Strong`] instances.
31 ///
32 /// This trait is implemented by "Brand" types (like [`ArcFnBrand`][crate::brands::ArcFnBrand]
33 /// and [`RcFnBrand`][crate::brands::RcFnBrand]) to provide a way to construct
34 /// and type-check wrappers over closures (`Arc<dyn Fn...>`, `Rc<dyn Fn...>`,
35 /// etc.) in a generic context, allowing library users to choose between
36 /// implementations at function call sites.
37 ///
38 /// Unlike [`CloneFn`](crate::classes::CloneFn), which provides cloneable
39 /// wrappers for use in applicative contexts, `Arrow` provides composable
40 /// wrappers for use in the optics system.
41 ///
42 /// The lifetime `'a` ensures the function doesn't outlive referenced data,
43 /// while generic types `A` and `B` represent the input and output types, respectively.
44 pub trait Arrow: Category + Strong {
45 /// The type of the function wrapper.
46 ///
47 /// This associated type represents the concrete type of the wrapper (e.g., `Rc<dyn Fn(A) -> B>`)
48 /// that dereferences to the underlying closure.
49 type Of<'a, A: 'a, B: 'a>: Deref<Target = dyn 'a + Fn(A) -> B>;
50
51 /// Lifts a pure function into an arrow.
52 ///
53 /// This function wraps the provided closure `f` into a composable function wrapper.
54 #[document_signature]
55 ///
56 #[document_type_parameters(
57 "The lifetime of the function and its captured data.",
58 "The input type of the function.",
59 "The output type of the function."
60 )]
61 ///
62 #[document_parameters("The closure to lift into an arrow.")]
63 #[document_returns("The wrapped function.")]
64 #[document_examples]
65 ///
66 /// ```
67 /// use fp_library::{
68 /// brands::*,
69 /// functions::*,
70 /// };
71 ///
72 /// let f = arrow::<RcFnBrand, _, _>(|x: i32| x * 2);
73 /// assert_eq!(f(5), 10);
74 /// ```
75 fn arrow<'a, A: 'a, B: 'a>(f: impl 'a + Fn(A) -> B) -> <Self as Arrow>::Of<'a, A, B>;
76 }
77
78 // No free function here: the `arrow` free function already exists in
79 // `profunctor.rs` and is re-exported via `functions.rs`. It lifts a
80 // pure function into any `Category + Profunctor` (which `Arrow`
81 // satisfies via its supertraits).
82}
83
84pub use inner::*;