rust_fp_categories/
monad.rs1use 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}