rust_fp_categories/
apply.rs1use std::rc::Rc;
2
3pub trait Apply {
4 type Elm;
5 type M<B>;
6
7 fn ap<B, F>(self, fs: Self::M<F>) -> Self::M<B>
8 where
9 F: Fn(&Self::Elm) -> B;
10}
11
12macro_rules! apply_numeric_impl {
15 ($($t:ty)*) => ($(
16 impl Apply for $t {
17 type Elm = $t;
18 type M<U> = U;
19
20 fn ap<B, F>(self, fs: Self::M<F>) -> Self::M<B>
21 where
22 F: Fn(&Self::Elm) -> B,
23 {
24 fs(&self)
25 }
26 }
27 )*)
28}
29
30apply_numeric_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
31
32impl<A> Apply for Rc<A> {
33 type Elm = A;
34 type M<U> = Rc<U>;
35
36 fn ap<B, F>(self, fs: Self::M<F>) -> Self::M<B>
37 where
38 F: Fn(&Self::Elm) -> B,
39 {
40 Rc::new(fs(&self))
41 }
42}
43
44impl<A> Apply for Box<A> {
45 type Elm = A;
46 type M<U> = Box<U>;
47
48 fn ap<B, F>(self, fs: Self::M<F>) -> Self::M<B>
49 where
50 F: Fn(&Self::Elm) -> B,
51 {
52 Box::new(fs(&self))
53 }
54}
55
56impl<A> Apply for Option<A> {
59 type Elm = A;
60 type M<U> = Option<U>;
61
62 fn ap<B, F>(self, fs: Self::M<F>) -> Self::M<B>
63 where
64 F: Fn(&Self::Elm) -> B,
65 {
66 Some(fs?(&self?))
67 }
68}
69
70impl<A, E: Clone> Apply for Result<A, E> {
71 type Elm = A;
72 type M<U> = Result<U, E>;
73
74 fn ap<B, F>(self, fs: Self::M<F>) -> Self::M<B>
75 where
76 F: Fn(&Self::Elm) -> B,
77 {
78 let x = self?;
79 let fs = fs?;
80 Ok(fs(&x))
81 }
82}
83
84impl<A> Apply for Vec<A> {
85 type Elm = A;
86 type M<U> = Vec<U>;
87
88 fn ap<B, F>(self, fs: Self::M<F>) -> Self::M<B>
89 where
90 F: Fn(&Self::Elm) -> B,
91 {
92 let zipped = self.iter().zip(fs.iter());
93 zipped.map(|(x, f)| f(x)).collect::<Vec<B>>()
94 }
95}