fp_library/functions.rs
1//! Contains 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
20use fp_macros::{doc_params, doc_type_params, hm_signature};
21// Auto-generate re-exports, passing in aliases for conflicting names.
22fp_macros::generate_function_re_exports!("src/classes", {
23 "category::identity": category_identity,
24 "cloneable_fn::new": cloneable_fn_new,
25 "function::new": fn_new,
26 "pointer::new": pointer_new,
27 "ref_counted_pointer::cloneable_new": ref_counted_pointer_new,
28 "send_ref_counted_pointer::send_new": send_ref_counted_pointer_new,
29 "semigroupoid::compose": semigroupoid_compose,
30 "send_cloneable_fn::new": send_cloneable_fn_new,
31});
32
33/// Composes two functions.
34///
35/// Takes two functions, `f` and `g`, and returns a new function that applies `g` to its argument,
36/// and then applies `f` to the result. This is equivalent to the mathematical composition `f ∘ g`.
37///
38/// ### Type Signature
39///
40#[hm_signature]
41///
42/// ### Type Parameters
43///
44#[doc_type_params(
45 "The input type of the inner function `g`.",
46 "The output type of `g` and the input type of `f`.",
47 "The output type of the outer function `f`.",
48 "The type of the outer function.",
49 "The type of the inner function."
50)]
51///
52/// ### Parameters
53///
54#[doc_params(
55 "The outer function to apply second.",
56 "The inner function to apply first.",
57 "The argument to be passed to the composed function."
58)]
59/// ### Returns
60///
61/// A new function that takes an `A` and returns a `C`.
62///
63/// ### Examples
64///
65/// ```rust
66/// use fp_library::functions::*;
67///
68/// let add_one = |x: i32| x + 1;
69/// let times_two = |x: i32| x * 2;
70/// let times_two_add_one = compose(add_one, times_two);
71///
72/// // 3 * 2 + 1 = 7
73/// assert_eq!(
74/// times_two_add_one(3),
75/// 7
76/// );
77/// ```
78pub fn compose<A, B, C, F, G>(
79 f: F,
80 g: G,
81) -> impl Fn(A) -> C
82where
83 F: Fn(B) -> C,
84 G: Fn(A) -> B,
85{
86 move |a| f(g(a))
87}
88
89/// Creates a constant function.
90///
91/// Returns a function that ignores its argument and always returns the provided value `a`.
92/// This is useful when a function is expected but a constant value is needed.
93///
94/// ### Type Signature
95///
96#[hm_signature]
97///
98/// ### Type Parameters
99///
100#[doc_type_params("The type of the value to return.", "The type of the argument to ignore.")]
101///
102/// ### Parameters
103///
104#[doc_params("The value to be returned by the constant function.", "The argument to be ignored.")]
105/// ### Returns
106///
107/// The first parameter.
108///
109/// ### Examples
110///
111/// ```rust
112/// use fp_library::functions::*;
113///
114/// assert_eq!(
115/// constant(true, false),
116/// true
117/// );
118/// ```
119pub fn constant<A: Clone, B>(
120 a: A,
121 _b: B,
122) -> A {
123 a
124}
125
126/// Flips the arguments of a binary function.
127///
128/// Returns a new function that takes its arguments in the reverse order of the input function `f`.
129/// If `f` takes `(a, b)`, the returned function takes `(b, a)`.
130///
131/// ### Type Signature
132///
133#[hm_signature]
134///
135/// ### Type Parameters
136///
137#[doc_type_params(
138 "The type of the first argument of the input function.",
139 "The type of the second argument of the input function.",
140 "The return type of the function.",
141 "The type of the input binary function."
142)]
143///
144/// ### Parameters
145///
146#[doc_params(
147 "A binary function.",
148 "The second argument (which will be passed as the first to `f`).",
149 "The first argument (which will be passed as the second to `f`)."
150)]
151/// ### Returns
152///
153/// A version of `f` that takes its arguments in reverse.
154///
155/// ### Examples
156///
157/// ```rust
158/// use fp_library::functions::*;
159///
160/// let subtract = |a, b| a - b;
161///
162/// // 0 - 1 = -1
163/// assert_eq!(
164/// flip(subtract)(1, 0),
165/// -1
166/// );
167/// ```
168pub fn flip<A, B, C, F>(f: F) -> impl Fn(B, A) -> C
169where
170 F: Fn(A, B) -> C,
171{
172 move |b, a| f(a, b)
173}
174
175/// The identity function.
176///
177/// Returns its input argument as is. This is often used as a default or placeholder function.
178///
179/// ### Type Signature
180///
181#[hm_signature]
182///
183/// ### Type Parameters
184///
185#[doc_type_params("The type of the value.")]
186///
187/// ### Parameters
188///
189#[doc_params("A value.")]
190///
191/// ### Returns
192///
193/// The same value `a`.
194///
195/// ### Examples
196///
197/// ```rust
198/// use fp_library::functions::*;
199///
200/// assert_eq!(
201/// identity(()),
202/// ()
203/// );
204/// ```
205pub fn identity<A>(a: A) -> A {
206 a
207}