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
use crate::{Applicative, Bind};

/// A `Monad` is like a burrito, and also anything which implements
/// [`Bind`](Bind) and [`Applicative`](Applicative).
///
/// A monad's primary function is to provide the [`Bind`](Bind) trait, but to
/// count as a monad a type must also implement [`Applicative`](Applicative),
/// which in turn requires you to implement [`Functor`](crate::Functor),
/// [`Pure`](crate::Pure) and [`Apply`](crate::Apply).
pub trait Monad<'a, A>: Bind<'a, A> + Applicative<'a, A> {}

impl<'a, M, A> Monad<'a, A> for M where M: Bind<'a, A> + Applicative<'a, A> {}

#[cfg(test)]
mod test {
    use crate::{Bind, Pure};

    #[test]
    fn warm_fuzzy_option() {
        let a = Option::pure(31337);
        let b = a.bind(|x| Option::pure(x.to_string()));
        assert_eq!(b, Option::Some("31337".to_string()));
    }

    #[test]
    fn warm_fuzzy_vec() {
        let a = vec![1, 2, 3];
        let b = a.bind(|x| vec![x, x + 1]);
        assert_eq!(b, vec![1, 2, 2, 3, 3, 4]);
    }
}