funlib/
lib.rs

1//! Functional Libary for Rust
2//!
3//! This is still a work in progess..
4//!
5//! Functor
6//!
7//! ```
8//! use funlib::Functor;
9//!
10//! let s = Some(3).fmap(|&a| a * 2); // this will produce Some(6)
11//!
12//! ```
13//!
14//! Monad
15//!
16//! ```
17//! use funlib::Monad;
18//!
19//! let s = Some(3).bind(|&a| Some(a * 2)); // this will produce Some(6)
20//!
21//! ```
22//!
23//!
24//! 
25#![deny(missing_docs)]
26#[macro_use] extern crate funlib_macros;
27pub mod functor;
28pub mod applicative;
29pub mod monad;
30pub mod semigroup;
31pub mod monoid;
32pub mod foldable;
33use std::rc::Rc;
34
35/// Higher Kinded Type helper for M<A> -> M<B>
36pub trait HKT<B> {
37  /// Current Type
38  type A;
39  /// Type M<B>
40  type M;
41}
42/// Higher kinded Type helper for M<A> -> M<A>
43pub trait HKST<'a, B> {
44  /// Current Type
45  type A;
46  /// Type M<A>
47  type M;
48}
49
50hkt!(Vec);
51hkt!(Option);
52hkt!(Box);
53hkt!(Rc);
54
55/// Functor type class
56pub trait Functor<B>: HKT<B> {
57  /// Functor map
58  /// # Examples
59  /// ```
60  /// use funlib::Functor;
61  /// let n = Some(1).fmap(|i| i * 4);
62  /// assert_eq!(Some(4), n);
63  /// ```
64  fn fmap<F>(&self, f: F) -> Self::M where F: Fn(&Self::A) -> B;
65}
66
67/// Applicative type class
68pub trait Applicative<B>: Functor<B> {
69  /// Lift values into the context of the Functor
70  ///
71  /// # Examples
72  /// ```
73  /// use funlib::Applicative;
74  /// let s1 = Option::<i8>::pure_(10);
75  /// let s2 = Option::pure_("hi");
76  /// let v = Vec::pure_(1);
77  /// ```
78  fn pure_(value: B) -> Self::M where Self: HKT<B, A=B>;
79  /// Apply function is almost the same as Functor map. but the function isn't A => B but A<F => B>
80  ///
81  /// # Examples
82  /// ```
83  /// use funlib::Applicative;
84  /// fn double(i: &i32) -> i32 { i * 2  }
85  /// let f: &dyn Fn(&i32) -> i32 = &|x| x * 2;
86  /// assert_eq!(Some(4), Some(2).ap(Some(f)));
87  /// assert_eq!(Some(4), Some(2).ap(Some(&double)));
88  /// ```
89  fn ap<F>(&self, f: <Self as HKT<F>>::M) -> <Self as HKT<B>>::M
90      where F: Fn(&<Self as HKT<B>>::A) -> B, Self:HKT<F>;
91}
92
93/// Monad type class
94pub trait Monad<B>: Applicative<B> {
95  /// Bind works like map but it flattens nested structures
96  ///
97  /// # Examples
98  /// ```
99  /// use funlib::Applicative;
100  /// use funlib::Monad;
101  /// fn over5(i: &i32) -> Option<i32> { if *i > 5 { Some(*i) } else { None }}
102  /// let a = Some(4).bind(over5);
103  /// let b = Some(6).bind(over5);
104  /// assert_eq!(None, a);
105  /// assert_eq!(Some(6), b);
106  /// ```
107  fn bind<F>(&self, f: F) -> Self::M where F: Fn(&Self::A) -> Self::M;
108}
109
110/// Semigroup type class
111pub trait Semigroup: Clone {
112  /// combine 2 of the same type
113  ///
114  /// # Examples
115  ///
116  /// ```
117  /// use funlib::Semigroup;
118  /// assert_eq!(4i32, 1i32.mappend(&3i32));
119  /// assert_eq!(Some(4i32), Some(1i32).mappend(&Some(3i32)));
120  /// ```
121  fn mappend(&self, other: &Self) -> Self;
122}
123
124/// Monoid type class extends the Semigroup and adds an empty function for the type
125pub trait Monoid: Semigroup {
126  /// empty function same as Default
127  ///
128  /// # Examples
129  ///
130  /// ```
131  /// use funlib::{Monoid, Semigroup, Foldable::*};
132  /// let sum = vec![1i32,2i32,3i32,4i32].fold(i32::mempty(), |b,a| i32::mappend(&b, a));
133  /// assert_eq!(10i32, sum);
134  /// assert_eq!(None::<i32>, Option::<i32>::mempty());
135  /// ```
136  fn mempty() -> Self;
137}
138
139/// Foldable mod containing the foldable type classes
140#[allow(non_snake_case)]
141pub mod Foldable {
142  use crate::{HKST, HKT, Monoid};
143  /// FoladableA is for endo type functions
144  pub trait FoldableA<'r, A: 'r>: HKST<'r, A> {
145    /// Reduces the values of the Foldable into a single value
146    ///
147    /// # Examples
148    ///
149    /// ```
150    /// use funlib::Foldable::*;
151    /// let v = vec![1,2,3,4];
152    /// let sum = v.fold(0, |b, a| a + b);
153    /// assert_eq!(10, sum);
154    /// ```
155    fn fold<F>(&'r self, z: A, f: F) -> A where F: FnMut(A, &A) -> A;
156    /// Using a Monoid reduce the values in the Foldable to a single value
157    /// # Examples
158    ///
159    /// ```
160    /// use funlib::Foldable::*;
161    /// let v = vec![1,2,3,4];
162    /// let sum = v.concat();
163    /// assert_eq!(10, sum);
164    /// ```
165    fn concat(&'r self) -> A where A: Monoid { self.fold(A::mempty(), |a,b| A::mappend(&a, b)) }
166    /// Find a value in the foldable, returns an Option<&_>
167    ///
168    /// # Examples
169    ///
170    /// ```
171    /// use funlib::Foldable::*;
172    /// let v = vec![1,2,3,4];
173    /// let s = v.find(|&a| a == 2);
174    /// let n = v.find(|&a| a == 5);
175    /// assert_eq!(Some(&2), s);
176    /// assert_eq!(None, n);
177    /// ```
178    fn find<F>(&'r self, f: F) -> Option<&A> where F: Fn(&A) -> bool;
179    /// Check if all values in the foldable returns true for function f
180    ///
181    /// # Examples
182    ///
183    /// ```
184    /// use funlib::Foldable::*;
185    /// let v = vec![1,2,3,4];
186    /// assert_eq!(true, v.all(|&a| a < 5));
187    /// assert_eq!(false, v.all(|&a| a < 4));
188    /// ```
189    fn all<F>(&'r self, f: F) -> bool where F: Fn(&A) -> bool;
190    /// Check if any valu ein the foldable returns true for function f
191    ///
192    /// # Examples
193    ///
194    /// ```
195    /// use funlib::Foldable::*;
196    /// let v = vec![1,2,3,4];
197    /// assert_eq!(true, v.any(|&a| a == 4));
198    /// assert_eq!(false, v.any(|&a| a == 5));
199    /// ```
200    fn any<F>(&'r self, f: F) -> bool where F: Fn(&A) -> bool;
201    /// Filters the foldable for values that meet the predicate
202    ///
203    /// # Examples
204    ///
205    /// ```
206    /// use funlib::Foldable::*;
207    /// let v = vec![1,2,3,4];
208    /// assert_eq!(vec![&1,&2], v.filter(|&a| a < 3));
209    /// ```
210    fn filter<F>(&'r self, f: F) -> Self::M where F: Fn(&A) -> bool;
211    /// Checks if the foldable is empty
212    ///
213    /// # Examples
214    ///
215    /// ```
216    /// use funlib::Foldable::*;
217    /// let v = vec![1,2,3,4];
218    /// let v2: Vec<i32> = vec![];
219    /// assert_eq!(false, v.is_empty());
220    /// assert_eq!(true, v2.is_empty());
221    /// ```
222    fn is_empty(&'r self) -> bool;
223    /// Checks if the foldable is non empty
224    ///
225    /// # Examples
226    ///
227    /// ```
228    /// use funlib::Foldable::*;
229    /// let v = vec![1,2,3,4];
230    /// let v2: Vec<i32> = vec![];
231    /// assert_eq!(true, v.non_empty());
232    /// assert_eq!(false, v2.non_empty());
233    /// ```
234    fn non_empty(&'r self) -> bool { !self.is_empty() }
235  }
236
237  /// FoldableS is for Foldables that is not a list of some kind, ex. Option
238  pub trait FoldableS<'r, A: 'r>: HKST<'r, A> {
239    /// Reduces the values of the Foldable into a single value
240    fn fold<F>(&'r self, z: A, f: F) -> A where F: Fn(&A) -> A;
241    /// Find a value in the foldable, returns an Option<&_>
242    fn find<F>(&'r self, f: F) -> Option<&A> where F: Fn(&A) -> bool;
243    /// Check if all values in the foldable returns true for function f
244    fn all<F>(&'r self, f: F) -> bool where F: Fn(&A) -> bool;
245    /// Check if any valu ein the foldable returns true for function f
246    fn any<F>(&'r self, f: F) -> bool where F: Fn(&A) -> bool;
247    /// Filters the foldable for values that meet the predicate
248    fn filter<F>(&'r self, f: F) -> Self::M where F: Fn(&A) -> bool;
249    /// Checks if the foldable is empty
250    fn is_empty(&'r self) -> bool;
251    /// Checks if the foldable is non empty.
252    fn non_empty(&'r self) -> bool { !self.is_empty() }
253  }
254
255  /// FoladableB is for Hinger Kinded Types where M<A> -> B / M<B>
256  pub trait FoldableB<B>: HKT<B> {
257    /// Reduces the values of the Foldable into a single value
258    ///
259    /// # Examples
260    ///
261    /// ```
262    /// use funlib::Foldable::*;
263    /// #[derive(Debug, PartialEq)]
264    /// struct Count(i32);
265    /// let v = vec![1,2,3,4];
266    /// let sum = v.fold_right(Count(0), |a, b| Count(a + b.0));
267    /// assert_eq!(Count(10), sum);
268    /// ```
269    fn fold_right<F>(&self, z: B, f: F) -> B where F: Fn(&Self::A, B) -> B;
270    /// Reduces the values of the Foldable into a single value
271    ///
272    /// # Examples
273    ///
274    /// ```
275    /// use funlib::Foldable::*;
276    /// #[derive(Debug, PartialEq)]
277    /// struct Count(i32);
278    /// let v = vec![1,2,3,4];
279    /// let sum: Count = v.fold_left(Count(0), |b, a| Count(a + b.0));
280    /// assert_eq!(Count(10), sum);
281    /// ```
282    fn fold_left<F>(&self, z: B, f: F) -> B where F: Fn(B, &Self::A) -> B;
283    /// Using a Monoid and a function to transform the Foldable values form A -> b to reduce the values in the Foldable to a single value of B
284    fn fold_map<F>(&self, f: F) -> B where F: Fn(&Self::A) -> B, B: Monoid { self.fold_left(B::mempty(), |b, a| B::mappend(&b, &f(&a))) }
285  }
286}