1trait Apply<'a, O> {
2 type Output;
3 fn applicative(self) -> Self::Output; }
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
30impl_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}