Skip to main content

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::*;