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 super::typeclasses::{
5	apply::apply, apply_first::apply_first, apply_second::apply_second, bind::bind, functor::map,
6	pure::pure,
7};
8
9/// Takes a function `f`, returns a new function that takes a function `g`,
10/// then returns the final composed function `f . g`.
11///
12/// forall a b c. (b -> c) -> (a -> b) -> a -> c
13///
14/// # Examples
15///
16/// ```rust
17/// use fp_library::functions::compose;
18///
19/// let add_one = |x: i32| x + 1;
20/// let times_two = |x: i32| x * 2;
21/// let times_two_add_one = compose(add_one)(times_two);
22///
23/// assert_eq!(times_two_add_one(3), 7); // 3 * 2 + 1 = 7
24/// ```
25pub fn compose<'a, A, B, C, F, G>(f: F) -> impl Fn(G) -> Box<dyn Fn(A) -> C + 'a>
26where
27	F: Fn(B) -> C + Clone + 'a,
28	G: Fn(A) -> B + 'a,
29{
30	move |g| {
31		let f = f.to_owned();
32		Box::new(move |a: A| f(g(a)))
33	}
34}
35
36/// Returns its first argument.
37///
38/// forall a b. a -> b -> a
39///
40/// # Examples
41///
42/// ```rust
43/// use fp_library::{functions::constant};
44///
45/// assert_eq!(constant(true)(false), true);
46/// ```
47pub fn constant<A, B>(a: A) -> impl Fn(B) -> A
48where
49	A: Clone,
50	B: Clone,
51{
52	move |_b| a.to_owned()
53}
54
55/// Returns a version of the input curried binary function
56/// with its arguments flipped.
57///
58/// forall a b c. (a -> b -> c) -> b -> a -> c
59///
60/// # Examples
61///
62/// ```rust
63/// use fp_library::functions::flip;
64///
65/// let subtract = |a| move |b| a - b;
66///
67/// assert_eq!(flip(subtract)(1)(0), -1); // 0 - 1 = -1
68/// ```
69pub fn flip<'a, A, B, C, F, G>(f: F) -> impl Fn(B) -> Box<dyn Fn(A) -> C + 'a>
70where
71	B: Clone + 'a,
72	F: Fn(A) -> G + Clone + 'a,
73	G: Fn(B) -> C,
74{
75	move |b| {
76		let f = f.to_owned();
77		Box::new(move |a| (f(a))(b.to_owned()))
78	}
79}
80
81/// Returns its input.
82///
83/// forall a. a -> a
84///
85/// # Examples
86///
87/// ```rust
88/// use fp_library::functions::identity;
89///
90/// assert_eq!(identity(()), ());
91/// ```
92pub fn identity<A>(a: A) -> A {
93	a
94}