fp-library 0.15.0

A functional programming library for Rust featuring your favourite higher-kinded types and type classes.
Documentation
//! Wrappers over closures for generic handling of functions in higher-kinded contexts.
//!
//! ### Examples
//!
//! ```
//! use fp_library::{
//! 	brands::*,
//! 	functions::*,
//! };
//!
//! let f = fn_new::<RcFnBrand, _, _>(|x: i32| x * 2);
//! assert_eq!(f(5), 10);
//! ```

#[fp_macros::document_module]
mod inner {
	use {
		crate::classes::{
			profunctor::*,
			*,
		},
		fp_macros::*,
		std::ops::Deref,
	};

	/// A trait for wrappers over closures, allowing for generic handling of functions in higher-kinded contexts.
	///
	/// This trait is implemented by "Brand" types (like [`ArcFnBrand`][crate::brands::ArcFnBrand]
	/// and [`RcFnBrand`][crate::brands::RcFnBrand]) to provide a way to construct
	/// and type-check wrappers over closures (`Arc<dyn Fn...>`, `Rc<dyn Fn...>`,
	/// etc.) in a generic context, allowing library users to choose between
	/// implementations at function call sites.
	///
	/// The lifetime `'a` ensures the function doesn't outlive referenced data,
	/// while generic types `A` and `B` represent the input and output types, respectively.
	pub trait Function: Category + Strong {
		/// The type of the function wrapper.
		///
		/// This associated type represents the concrete type of the wrapper (e.g., `Rc<dyn Fn(A) -> B>`)
		/// that dereferences to the underlying closure.
		type Of<'a, A: 'a, B: 'a>: Deref<Target = dyn 'a + Fn(A) -> B>;

		/// Creates a new function wrapper.
		///
		/// This function wraps the provided closure `f` into a function wrapper.
		#[document_signature]
		///
		#[document_type_parameters(
			"The lifetime of the function and its captured data.",
			"The input type of the function.",
			"The output type of the function."
		)]
		///
		#[document_parameters("The closure to wrap.", "The input value to the function.")]
		#[document_returns("The wrapped function.")]
		#[document_examples]
		///
		/// ```
		/// use fp_library::{
		/// 	brands::*,
		/// 	functions::*,
		/// };
		///
		/// let f = fn_new::<RcFnBrand, _, _>(|x: i32| x * 2);
		/// assert_eq!(f(5), 10);
		/// ```
		fn new<'a, A: 'a, B: 'a>(f: impl 'a + Fn(A) -> B) -> <Self as Function>::Of<'a, A, B>;
	}

	/// Creates a new function wrapper.
	///
	/// Free function version that dispatches to [the type class' associated function][`Function::new`].
	#[document_signature]
	///
	#[document_type_parameters(
		"The lifetime of the function and its captured data.",
		"The brand of the function wrapper.",
		"The input type of the function.",
		"The output type of the function."
	)]
	///
	#[document_parameters("The closure to wrap.", "The input value to the function.")]
	#[document_returns("The wrapped function.")]
	#[document_examples]
	///
	/// ```
	/// use fp_library::{
	/// 	brands::*,
	/// 	functions::*,
	/// };
	///
	/// let f = fn_new::<RcFnBrand, _, _>(|x: i32| x * 2);
	/// assert_eq!(f(5), 10);
	/// ```
	pub fn new<'a, Brand, A, B>(f: impl 'a + Fn(A) -> B) -> <Brand as Function>::Of<'a, A, B>
	where
		Brand: Function, {
		Brand::new(f)
	}
}

pub use inner::*;