fp_library/functions.rs
1//! Generic, helper free functions, combinators and re-exports of [typeclass][crate::typeclasses]
2//! free functions that dispatch to associated functions of typeclass instances.
3
4use crate::typeclasses::{ClonableFn, clonable_fn::ApplyFn};
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 traversable::{sequence, traverse},
16};
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::{brands::RcFnBrand, functions::compose};
37/// use std::rc::Rc;
38///
39/// let add_one = Rc::new(|x: i32| x + 1);
40/// let times_two = Rc::new(|x: i32| x * 2);
41/// let times_two_add_one = compose::<RcFnBrand, _, _, _>(add_one)(times_two);
42///
43/// // 3 * 2 + 1 = 7
44/// assert_eq!(
45/// times_two_add_one(3),
46/// 7
47/// );
48/// ```
49pub fn compose<'a, ClonableFnBrand: 'a + ClonableFn, A: 'a, B: 'a, C: 'a>(
50 f: ApplyFn<'a, ClonableFnBrand, B, C>
51) -> ApplyFn<
52 'a,
53 ClonableFnBrand,
54 ApplyFn<'a, ClonableFnBrand, A, B>,
55 ApplyFn<'a, ClonableFnBrand, A, C>,
56> {
57 ClonableFnBrand::new(move |g: ApplyFn<'a, ClonableFnBrand, _, _>| {
58 let f = f.clone();
59 ClonableFnBrand::new(move |a| f(g(a)))
60 })
61}
62
63/// Returns its first argument.
64///
65/// # Type Signature
66///
67/// `forall a b. a -> b -> a`
68///
69/// # Parameters
70///
71/// * `a`: A value.
72/// * `b`: Some other value.
73///
74/// # Returns
75///
76/// The first value.
77///
78/// # Examples
79///
80/// ```rust
81/// use fp_library::{brands::RcFnBrand, functions::constant};
82///
83/// assert_eq!(
84/// constant::<RcFnBrand, _, _>(true)(false),
85/// true
86/// );
87/// ```
88pub fn constant<'a, ClonableFnBrand: 'a + ClonableFn, A: 'a + Clone, B: Clone>(
89 a: A
90) -> ApplyFn<'a, ClonableFnBrand, B, A> {
91 ClonableFnBrand::new(move |_b| a.to_owned())
92}
93
94/// Returns a version of the input curried binary function
95/// with its arguments flipped.
96///
97/// # Type Signature
98///
99/// `forall a b c. (a -> b -> c) -> b -> a -> c`
100///
101/// # Parameters
102///
103/// * `f`: A curried binary function.
104///
105/// # Returns
106///
107/// A version of `f` that takes its arguments in reverse.
108///
109/// # Examples
110///
111/// ```rust
112/// use fp_library::{brands::RcFnBrand, functions::flip, typeclasses::clonable_fn::ApplyFn};
113/// use std::rc::Rc;
114///
115/// let subtract: ApplyFn<RcFnBrand, _, ApplyFn<RcFnBrand, _, _>> = Rc::new(|a| Rc::new(move |b| a - b));
116///
117/// // 0 - 1 = -1
118/// assert_eq!(
119/// flip::<RcFnBrand, _, _, _>(subtract)(1)(0),
120/// -1
121/// );
122/// ```
123pub fn flip<'a, ClonableFnBrand: 'a + ClonableFn, A: 'a, B: 'a + Clone, C: 'a>(
124 f: ApplyFn<'a, ClonableFnBrand, A, ApplyFn<'a, ClonableFnBrand, B, C>>
125) -> ApplyFn<'a, ClonableFnBrand, B, ApplyFn<'a, ClonableFnBrand, A, C>> {
126 ClonableFnBrand::new(move |b: B| {
127 let f = f.clone();
128 ClonableFnBrand::new(move |a| (f(a))(b.to_owned()))
129 })
130}
131
132/// Returns its input.
133///
134/// # Type Signature
135///
136/// `forall a. a -> a`
137///
138/// # Parameters
139///
140/// * `a`: A value.
141///
142/// # Returns
143///
144/// The same value.
145///
146/// # Examples
147///
148/// ```rust
149/// use fp_library::functions::identity;
150///
151/// assert_eq!(
152/// identity(()),
153/// ()
154/// );
155/// ```
156pub fn identity<A>(a: A) -> A {
157 a
158}