curri/
apply.rs

1trait Apply<'a, O> {
2    type Output;
3    fn applicative(self) -> Self::Output; // app is short for applicative
4}
5
6macro_rules! impl_apply {
7    () => {
8        impl<'a, F, O> Apply<'a, (O,)> for F
9          where  F: Fn() -> O + 'a,
10        {
11            type Output =Box<F>;
12            fn applicative(self) -> Self::Output {
13                Box::new(self)
14            }
15        }
16    };
17    ($(($P:ident, $p:ident)),*) => {
18        impl<'a, F, O, $($P),*> Apply<'a, (O, $($P),*)> for F
19        where
20            F: Fn($($P),*) -> O + 'a,
21        {
22            type Output = Box<dyn Fn(($($P),*,))->O + 'a>;
23            fn applicative(self) -> Self::Output {
24                Box::new(move |($($p),*,):($($P),*,)| self($($p),*))
25            }
26        }
27    };
28}
29
30// all_tuples!(impl_apply, 0, 8, P, p_);
31impl_apply!();
32impl_apply!((P0, p0));
33impl_apply!((P0, p0), (P1, p1));
34impl_apply!((P0, p0), (P1, p1), (P2, p2));
35impl_apply!((P0, p0), (P1, p1), (P2, p2), (P3, p3));
36impl_apply!((P0, p0), (P1, p1), (P2, p2), (P3, p3), (P4, p4));
37impl_apply!((P0, p0), (P1, p1), (P2, p2), (P3, p3), (P4, p4), (P5, p5));
38impl_apply!((P0, p0), (P1, p1), (P2, p2), (P3, p3), (P4, p4), (P5, p5), (P6, p6));
39
40#[macro_export]
41macro_rules! apply {
42    ($e: expr) => {
43        $e.applicative()
44    };
45}
46#[cfg(test)]
47mod tests {
48    use super::*;
49
50    #[test]
51    fn test_apply_closure() {}
52
53    #[test]
54    fn test_apply_macro() {
55        let multiply = |a, b| a * b;
56        let multiply_fn = multiply.applicative();
57        assert_eq!(multiply_fn((3, 4)), 12);
58        assert_eq!(multiply_fn((3, 4)), 12);
59    }
60}