fp_library/
functions.rs

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