meowth/core/
applicative.rs1use crate::core::*;
4
5pub trait Applicative: Functor + Monoidal {
10 fn pure<A>(a: A) -> Self::Wrapped<A>
21 where
22 Self: Id<Self::Wrapped<A>>,
23 for<'a> A: Clone + 'a;
24
25 fn ap<B, F>(self, ff: Self::Wrapped<F>) -> Self::Wrapped<B>
27 where
28 for<'a> F: Fn(Self::Unwrapped) -> B + 'a;
29
30 fn ap2<B, C, F>(self, _b: Self::Wrapped<B>, _f: Self::Wrapped<F>) -> Self::Wrapped<C>
47 where
48 for<'a> F: Fn(Self::Unwrapped, B) -> C + 'a,
49 for<'a> B: 'a,
50 {
51 unimplemented!()
52 }
53}
54
55impl<T> Applicative for Option<T> {
56 fn pure<A>(a: A) -> Option<A> {
57 Some(a)
58 }
59
60 fn ap<B, F>(self, ff: Option<F>) -> Option<B>
61 where
62 F: Fn(T) -> B,
63 {
64 match (self, ff) {
65 (Some(a), Some(f)) => Some(f(a)),
66 _ => None,
67 }
68 }
69
70 fn ap2<B, C, F>(self, b: Option<B>, f: Option<F>) -> Option<C>
71 where
72 for<'a> F: Fn(T, B) -> C + 'a,
73 for<'a> B: 'a,
74 {
75 match self.product(b).product(f) {
76 Some(((a, b), f)) => Some(f(a, b)),
77 _ => None,
78 }
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 #[test]
87 fn test_applicative() {
88 let x = Option::pure(1);
89 assert_eq!(x, Some(1));
90
91 let x = Some(1);
92 let y = Some(2.0);
93 let z = x.product(y);
94 assert_eq!(z, Some((1, 2.0)));
95
96 let x = Some(1);
97 let y = Some(|x: i32| x as f64 / 2.0);
98 let z = x.ap(y);
99 assert_eq!(z, Some(0.5));
100
101 let x = None;
102 let y = Some(|x: i32| x as f64 / 2.0);
103 let z = x.ap(y);
104 assert_eq!(z, None);
105
106 let x = Some(1);
107 let y = Some(2.0);
108 let z = Some(|a: i32, b: f64| a as f64 + b);
109 let w = x.ap2(y, z);
110 assert_eq!(w, Some(3.0));
111 }
112}