rust_fp_categories/
apply.rs

1use 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
12// ---
13
14macro_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
56// ---
57
58impl<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}