Skip to main content

fp_library/classes/
pipe.rs

1//! Left-to-right function application via method syntax.
2//!
3//! Provides the [`Pipe`] trait for pipeline-style composition, similar to
4//! PureScript's `#` operator or Haskell's `&` operator.
5//!
6//! ### Examples
7//!
8//! ```
9//! use fp_library::{
10//! 	brands::*,
11//! 	classes::*,
12//! 	functions::*,
13//! };
14//!
15//! let result = Some(5).pipe(|x| map::<OptionBrand, _, _>(|n| n + 1, x));
16//!
17//! assert_eq!(result, Some(6));
18//! ```
19
20#[fp_macros::document_module]
21mod inner {
22	use fp_macros::*;
23
24	/// A trait for left-to-right function application via method syntax.
25	///
26	/// `Pipe` provides the `.pipe()` method on all sized types via a blanket
27	/// implementation, enabling pipeline-style composition similar to
28	/// PureScript's `#` operator or Haskell's `&` operator.
29	///
30	/// This is particularly useful for composing operations on types where
31	/// inherent methods are not available (e.g., stdlib types like `Option`
32	/// and `Vec`).
33	#[document_parameters("The value to pipe.")]
34	pub trait Pipe: Sized {
35		/// Pipes `self` into a function, enabling left-to-right composition.
36		///
37		/// Applies `f` to `self` and returns the result. This is the method
38		/// syntax version of [`pipe`].
39		#[document_signature]
40		///
41		#[document_type_parameters("The return type of the function.")]
42		///
43		#[document_parameters("The function to apply to the value.")]
44		///
45		#[document_returns("The result of applying `f` to `self`.")]
46		#[document_examples]
47		///
48		/// ```
49		/// use fp_library::{
50		/// 	brands::*,
51		/// 	classes::*,
52		/// 	functions::*,
53		/// };
54		///
55		/// let result = Some(5)
56		/// 	.pipe(|x| map::<OptionBrand, _, _>(|n| n + 1, x))
57		/// 	.pipe(|x| bind::<OptionBrand, _, _>(x, |n| if n > 3 { Some(n) } else { None }));
58		///
59		/// assert_eq!(result, Some(6));
60		/// ```
61		fn pipe<B>(
62			self,
63			f: impl FnOnce(Self) -> B,
64		) -> B {
65			f(self)
66		}
67	}
68
69	#[document_type_parameters("The type that implements Pipe.")]
70	impl<T> Pipe for T {}
71
72	/// Pipes a value into a function, enabling left-to-right composition.
73	///
74	/// Free function version of [`Pipe::pipe`]. Applies `f` to `a` and
75	/// returns the result. This is equivalent to PureScript's `applyFlipped`
76	/// or Haskell's `(&)`.
77	#[document_signature]
78	///
79	#[document_type_parameters("The type of the input value.", "The return type of the function.")]
80	///
81	#[document_parameters("The value to pipe.", "The function to apply to the value.")]
82	///
83	#[document_returns("The result of applying `f` to `a`.")]
84	#[document_examples]
85	///
86	/// ```
87	/// use fp_library::functions::*;
88	///
89	/// let result = pipe(5, |x| x + 1);
90	/// assert_eq!(result, 6);
91	/// ```
92	pub fn pipe<A, B>(
93		a: A,
94		f: impl FnOnce(A) -> B,
95	) -> B {
96		f(a)
97	}
98}
99
100pub use inner::*;