fp_library/functions.rs
1//! Generic, helper free functions and re-exports of free versions
2//! of type class functions.
3//!
4//! This module provides a collection of utility functions commonly found in functional programming,
5//! such as function composition, constant functions, and identity functions. It also re-exports
6//! free function versions of methods defined in various type classes (traits) for convenience.
7//!
8//! ### Examples
9//!
10//! ```
11//! use fp_library::{brands::*, functions::*};
12//!
13//! let f = |x: i32| x + 1;
14//! let g = |x: i32| x * 2;
15//! let h = compose::<i32, i32, _, _, _>(f, g);
16//!
17//! assert_eq!(map::<OptionBrand, _, _, _>(h, Some(5)), Some(11));
18//! ```
19
20// Auto-generate re-exports, passing in aliases for conflicting names.
21fp_macros::generate_reexports!("src/classes", {
22 "category::identity": category_identity,
23 "clonable_fn::new": clonable_fn_new,
24 "function::new": fn_new,
25 "once::new": once_new,
26 "once::get": once_get,
27 "once::get_mut": once_get_mut,
28 "once::set": once_set,
29 "once::get_or_init": once_get_or_init,
30 "once::into_inner": once_into_inner,
31 "once::take": once_take,
32 "semigroupoid::compose": semigroupoid_compose,
33 "send_clonable_fn::new": send_clonable_fn_new,
34});
35
36/// Composes two functions.
37///
38/// Takes two functions, `f` and `g`, and returns a new function that applies `g` to its argument,
39/// and then applies `f` to the result. This is equivalent to the mathematical composition `f ∘ g`.
40///
41/// ### Type Signature
42///
43/// `forall a c b. (b -> c, a -> b) -> (a -> c)`
44///
45/// ### Type Parameters
46///
47/// * `A`: The input type of the inner function `g`.
48/// * `C`: The output type of the outer function `f`.
49/// * `B`: The output type of `g` and the input type of `f`.
50/// * `F`: The type of the outer function.
51/// * `G`: The type of the inner function.
52///
53/// ### Parameters
54///
55/// * `f`: The outer function to apply second.
56/// * `g`: The inner function to apply first.
57///
58/// ### Returns
59///
60/// A new function that takes an `A` and returns a `C`.
61///
62/// ### Examples
63///
64/// ```rust
65/// use fp_library::functions::*;
66///
67/// let add_one = |x: i32| x + 1;
68/// let times_two = |x: i32| x * 2;
69/// let times_two_add_one = compose::<i32, i32, _, _, _>(add_one, times_two);
70///
71/// // 3 * 2 + 1 = 7
72/// assert_eq!(
73/// times_two_add_one(3),
74/// 7
75/// );
76/// ```
77pub fn compose<A, C, B, F, G>(
78 f: F,
79 g: G,
80) -> impl Fn(A) -> C
81where
82 F: Fn(B) -> C,
83 G: Fn(A) -> B,
84{
85 move |a| f(g(a))
86}
87
88/// Creates a constant function.
89///
90/// Returns a function that ignores its argument and always returns the provided value `a`.
91/// This is useful when a function is expected but a constant value is needed.
92///
93/// ### Type Signature
94///
95/// `forall b a. a -> (b -> a)`
96///
97/// ### Type Parameters
98///
99/// * `B`: The type of the argument to ignore.
100/// * `A`: The type of the value to return.
101///
102/// ### Parameters
103///
104/// * `a`: The value to be returned by the constant function.
105///
106/// ### Returns
107///
108/// A function that takes any value of type `B` and returns `a`.
109///
110/// ### Examples
111///
112/// ```rust
113/// use fp_library::functions::*;
114///
115/// assert_eq!(
116/// constant::<bool, _>(true)(false),
117/// true
118/// );
119/// ```
120pub fn constant<B, A: Clone>(a: A) -> impl Fn(B) -> A {
121 move |_| a.clone()
122}
123
124/// Flips the arguments of a binary function.
125///
126/// Returns a new function that takes its arguments in the reverse order of the input function `f`.
127/// If `f` takes `(a, b)`, the returned function takes `(b, a)`.
128///
129/// ### Type Signature
130///
131/// `forall a b c. ((a, b) -> c) -> ((b, a) -> c)`
132///
133/// ### Type Parameters
134///
135/// * `A`: The type of the first argument of the input function.
136/// * `B`: The type of the second argument of the input function.
137/// * `C`: The return type of the function.
138/// * `F`: The type of the input binary function.
139///
140/// ### Parameters
141///
142/// * `f`: A binary function.
143///
144/// ### Returns
145///
146/// A version of `f` that takes its arguments in reverse.
147///
148/// ### Examples
149///
150/// ```rust
151/// use fp_library::functions::*;
152///
153/// let subtract = |a, b| a - b;
154///
155/// // 0 - 1 = -1
156/// assert_eq!(
157/// flip::<i32, i32, _, _>(subtract)(1, 0),
158/// -1
159/// );
160/// ```
161pub fn flip<A, B, C, F>(f: F) -> impl Fn(B, A) -> C
162where
163 F: Fn(A, B) -> C,
164{
165 move |b, a| f(a, b)
166}
167
168/// The identity function.
169///
170/// Returns its input argument as is. This is often used as a default or placeholder function.
171///
172/// ### Type Signature
173///
174/// `forall a. a -> a`
175///
176/// ### Type Parameters
177///
178/// * `A`: The type of the value.
179///
180/// ### Parameters
181///
182/// * `a`: A value.
183///
184/// ### Returns
185///
186/// The same value `a`.
187///
188/// ### Examples
189///
190/// ```rust
191/// use fp_library::functions::*;
192///
193/// assert_eq!(
194/// identity(()),
195/// ()
196/// );
197/// ```
198pub fn identity<A>(a: A) -> A {
199 a
200}