rust_fp_categories/
monad.rs

1use std::rc::Rc;
2
3use crate::{Applicative, Bind};
4
5pub trait Monad: Bind + Applicative {}
6
7macro_rules! monad_numeric_impl {
8    ($($t:ty)*) => ($(
9       impl Monad for $t {}
10    )*)
11}
12
13monad_numeric_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
14
15impl<A> Monad for Rc<A> {}
16impl<A> Monad for Box<A> {}
17
18impl<A> Monad for Option<A> {}
19impl<A, E: Clone> Monad for Result<A, E> {}
20impl<A> Monad for Vec<A> {}
21
22#[cfg(test)]
23mod laws {
24    use crate::{Bind, Pure};
25
26    #[quickcheck]
27    fn monad_left_identity_law(n: i64) {
28        assert_eq!(Option::pure(n).bind(|x| Option::pure(*x)), Option::pure(n))
29    }
30
31    #[quickcheck]
32    fn monad_right_identity_law(n: i64) {
33        assert_eq!(
34            Option::pure(n)
35                .bind(|x| Option::pure(*x))
36                .bind(|y| Option::pure(*y)),
37            Option::pure(n).bind(|x| Option::pure(*x).bind(|y| Option::pure(*y)))
38        )
39    }
40}