1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
use applicative::Applicative;
use bind::Bind;
use std::rc::Rc;

pub trait Monad: Bind + Applicative {}

macro_rules! monad_numeric_impl {
    ($($t:ty)*) => ($(
       impl Monad for $t {}
    )*)
}

monad_numeric_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }

impl<A> Monad for Rc<A> {}
impl<A> Monad for Box<A> {}

impl<A> Monad for Option<A> {}
impl<A, E: Clone> Monad for Result<A, E> {}
impl<A> Monad for Vec<A> {}

#[cfg(test)]
mod laws {
    use bind::Bind;
    use pure::Pure;

    #[quickcheck]
    fn monad_left_identity_law(n: i64) {
        assert_eq!(Option::pure(n).bind(|x| Option::pure(*x)), Option::pure(n))
    }

    #[quickcheck]
    fn monad_right_identity_law(n: i64) {
        assert_eq!(
            Option::pure(n)
                .bind(|x| Option::pure(*x))
                .bind(|y| Option::pure(*y)),
            Option::pure(n).bind(|x| Option::pure(*x).bind(|y| Option::pure(*y)))
        )
    }
}