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