fp_library/
functions.rs

1//! Generic, helper free functions, combinators and re-exports of [typeclass][crate::typeclasses]
2//! functions that dispatch to instance methods.
3
4use crate::aliases::ClonableFn;
5pub use crate::typeclasses::{
6	apply::apply,
7	apply_first::apply_first,
8	apply_second::apply_second,
9	bind::bind,
10	foldable::{fold_left, fold_map, fold_right},
11	functor::map,
12	monoid::empty,
13	pure::pure,
14	semigroup::append,
15};
16use std::sync::Arc;
17
18/// Takes functions `f` and `g` and returns the function `f . g` (`f` composed with `g`).
19///
20/// # Type Signature
21///
22/// `forall a b c. (b -> c) -> (a -> b) -> a -> c`
23///
24/// # Parameters
25///
26/// * `f`: A function from values of type `B` to values of type `C`.
27/// * `g`: A function from values of type `A` to values of type `B`.
28///
29/// # Returns
30///
31/// A function from values of type `A` to values of type `C`.
32///
33/// # Examples
34///
35/// ```rust
36/// use fp_library::functions::compose;
37/// use std::sync::Arc;
38///
39/// let add_one = Arc::new(|x: i32| x + 1);
40/// let times_two = Arc::new(|x: i32| x * 2);
41/// let times_two_add_one = compose(add_one)(times_two);
42///
43/// assert_eq!(times_two_add_one(3), 7); // 3 * 2 + 1 = 7
44/// ```
45pub fn compose<'a, A: 'a, B: 'a, C: 'a>(
46	f: ClonableFn<'a, B, C>
47) -> ClonableFn<'a, ClonableFn<'a, A, B>, ClonableFn<'a, A, C>> {
48	Arc::new(move |g: ClonableFn<'a, A, B>| {
49		let f = f.clone();
50		Arc::new(move |a: A| f(g(a)))
51	})
52}
53
54/// Returns its first argument.
55///
56/// # Type Signature
57///
58/// `forall a b. a -> b -> a`
59///
60/// # Parameters
61///
62/// * `a`: A value.
63/// * `b`: Some other value.
64///
65/// # Returns
66///
67/// The first value.
68///
69/// # Examples
70///
71/// ```rust
72/// use fp_library::{functions::constant};
73///
74/// assert_eq!(constant(true)(false), true);
75/// ```
76pub fn constant<A, B>(a: A) -> impl Fn(B) -> A
77where
78	A: Clone,
79	B: Clone,
80{
81	move |_b| a.to_owned()
82}
83
84/// Returns a version of the input curried binary function
85/// with its arguments flipped.
86///
87/// # Type Signature
88///
89/// `forall a b c. (a -> b -> c) -> b -> a -> c`
90///
91/// # Parameters
92///
93/// * `f`: A curried binary function.
94///
95/// # Returns
96///
97/// A version of `f` that takes its arguments in reverse.
98///
99/// # Examples
100///
101/// ```rust
102/// use fp_library::{aliases::ClonableFn, functions::flip};
103/// use std::sync::Arc;
104///
105/// let subtract: ClonableFn<_, ClonableFn<_, _>> = Arc::new(|a| Arc::new(move |b| a - b));
106///
107/// assert_eq!(flip(subtract)(1)(0), -1); // 0 - 1 = -1
108/// ```
109pub fn flip<'a, A: 'a, B: 'a + Clone, C: 'a>(
110	f: ClonableFn<'a, A, ClonableFn<'a, B, C>>
111) -> ClonableFn<'a, B, ClonableFn<'a, A, C>> {
112	Arc::new(move |b: B| {
113		let f = f.clone();
114		Arc::new(move |a: A| (f(a))(b.to_owned()))
115	})
116}
117
118/// Returns its input.
119///
120/// # Type Signature
121///
122/// `forall a. a -> a`
123///
124/// # Parameters
125///
126/// * `a`: A value.
127///
128/// # Returns
129///
130/// The same value.
131///
132/// # Examples
133///
134/// ```rust
135/// use fp_library::functions::identity;
136///
137/// assert_eq!(identity(()), ());
138/// ```
139pub fn identity<A>(a: A) -> A {
140	a
141}