1use super::applicative::Applicative;
4use super::*;
5use super::types::*;
6
7pub trait Monad: Applicative {
8 fn bind<A, B, F: Fn(A) -> K1<Self, B>>(a: K1<Self, A>, f: F) -> K1<Self, B>;
9}
10
11impl Monad for OptionC {
12 fn bind<A, B, G: Fn(A) -> K1<Self, B>>(a: K1<Self, A>, g: G) -> K1<Self, B> {
13 match a.into_inner() {
14 Some(x) => g(x),
15 None => OptionC::new(None),
16 }
17 }
18}
19
20impl Monad for VecC {
21 fn bind<A, B, G: Fn(A) -> K1<Self, B>>(a: K1<Self, A>, g: G) -> K1<Self, B> {
22 Self::new(
23 a.into_inner()
24 .into_iter()
25 .flat_map(move |x| g(x).into_inner())
26 .collect()
27 )
28 }
29}
30
31#[cfg(test)]
32mod test {
33 use super::*;
34
35 fn check_law_left_identity<M: Monad, A, B, F>(a: A, f: F)
36 where
37 M: Kind1<B>,
38 A: Clone,
39 F: Fn(A) -> K1<M, B> + Clone,
40 K1<M, B>: PartialEq + Clone + core::fmt::Debug,
41 {
42 let return_bind = M::bind(M::pure(a.clone()), f.clone());
43 let just_call = f(a);
44 assert_eq!(return_bind, just_call);
45 }
46
47 fn check_law_right_identity<T: Clone, M: Monad>(m: K1<M, T>)
48 where
49 M: Kind1<T>,
50 K1<M, T>: PartialEq + Clone + core::fmt::Debug,
51 {
52 let m_return = M::bind(m.clone(), M::pure);
53 assert_eq!(m_return, m);
54 }
55
56 fn check_law_associativity<A, B, C, M: Monad, F, G>(m: K1<M, A>, f: F, g: G)
57 where
58 M: Kind1<A> + Kind1<C>,
59 K1<M, A>: Clone,
60 K1<M, C>: PartialEq + Clone + core::fmt::Debug,
61 F: Fn(A) -> K1<M, B> + Clone,
62 G: Fn(B) -> K1<M, C> + Clone,
63 {
64 let left_first = M::bind(M::bind(m.clone(), f.clone()), g.clone());
65 let right_first = M::bind(m, move |x| M::bind(f(x), g.clone()));
66 assert_eq!(left_first, right_first);
67 }
68
69 #[test]
70 fn option_monad_law_left_identity() {
71 check_law_left_identity(42, |x| OptionC::new(Some(x + 1)));
72 }
73
74 #[test]
75 fn option_monad_law_right_identity() {
76 check_law_right_identity::<i32, _>(OptionC::new(None));
77 check_law_right_identity(OptionC::new(Some(42)));
78 }
79
80 #[test]
81 fn option_monad_law_associativity() {
82 check_law_associativity(
83 OptionC::new(Some(42)),
84 |x| OptionC::new(Some(x + 1)),
85 |x| OptionC::new(Some(x * 2)),
86 );
87 check_law_associativity::<i32, _, _, _, _, _>(
88 OptionC::new(None),
89 |x| OptionC::new(Some(x + 1)),
90 |x| OptionC::new(Some(x * 2)),
91 );
92 check_law_associativity::<_, i32, _, _, _, _>(
93 OptionC::new(Some(42)),
94 |_| OptionC::new(None),
95 |x| OptionC::new(Some(x * 2)),
96 );
97 check_law_associativity::<_, _, i32, _, _, _>(
98 OptionC::new(Some(42)),
99 |x| OptionC::new(Some(x + 1)),
100 |_| OptionC::new(None),
101 );
102 }
103
104 #[test]
105 fn vec_monad_law_left_identity() {
106 check_law_left_identity(42, |x| VecC::new(vec![x + 1]));
107 }
108
109 #[test]
110 fn vec_monad_law_right_identity() {
111 check_law_right_identity::<i32, _>(VecC::new(vec![]));
112 check_law_right_identity(VecC::new(vec![42]));
113 }
114
115 #[test]
116 fn vec_monad_law_associativity() {
117 check_law_associativity(
118 VecC::new(vec![42, 0]),
119 |x| VecC::new(vec![x + 1, x - 1]),
120 |x| VecC::new(vec![x * 2, x]),
121 );
122 check_law_associativity::<i32, _, _, _, _, _>(
123 VecC::new(vec![]),
124 |x| VecC::new(vec![x + 1, x - 1]),
125 |x| VecC::new(vec![x * 2, x]),
126 );
127 check_law_associativity::<_, i32, _, _, _, _>(
128 VecC::new(vec![42, 0]),
129 |_| VecC::new(vec![]),
130 |x| VecC::new(vec![x * 2, x]),
131 );
132 check_law_associativity::<_, _, i32, _, _, _>(
133 VecC::new(vec![42, 0]),
134 |x| VecC::new(vec![x + 1, x - 1]),
135 |_| VecC::new(vec![]),
136 );
137 }
138}