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}