1use core::marker::PhantomData;
4
5use crate::functor::Functor;
6
7pub trait Apply<A, B>: Functor<B> {
9 fn ap(self, fa: Self::Target<A>) -> Self::Target<B>
26 where
27 Self::Param: FnMut(A) -> B;
28}
29
30#[macro_export]
32macro_rules! apply_iter {
33 ($name:ident) => {
34 impl<F, A: Clone, B> $crate::apply::Apply<A, B> for $name<F> {
35 #[inline]
36 fn ap(self, fa: Self::Target<A>) -> Self::Target<B>
37 where
38 Self::Param: FnMut(A) -> B,
39 {
40 self.into_iter()
41 .flat_map(|mut f| fa.clone().into_iter().map(move |a| f(a)))
42 .collect::<$name<B>>()
43 }
44 }
45 };
46 ($name:ident, $ct:tt $(+ $dt:tt )*) => {
47 impl<F: $ct $(+ $dt )*, A: Clone, B: $ct $(+ $dt )*> $crate::apply::Apply<A, B> for $name<F> {
48 #[inline]
49 fn ap(self, fa: Self::Target<A>) -> Self::Target<B>
50 where
51 Self::Param: FnMut(A) -> B,
52 {
53 self.into_iter()
54 .flat_map(|mut f| fa.clone().into_iter().map(move |a| f(a)))
55 .collect::<$name<B>>()
56 }
57 }
58 };
59}
60
61impl<F, A, B> Apply<A, B> for PhantomData<F> {
62 #[inline]
63 fn ap(self, _fa: PhantomData<A>) -> PhantomData<B>
64 where
65 F: FnOnce(A) -> B,
66 {
67 PhantomData
68 }
69}
70
71impl<F, A, B> Apply<A, B> for Option<F> {
72 #[inline]
73 fn ap(self, fa: Option<A>) -> Option<B>
74 where
75 F: FnOnce(A) -> B,
76 {
77 match (self, fa) {
78 (Some(f), Some(a)) => Some(f(a)),
79 _ => None,
80 }
81 }
82}
83
84impl<F, A, B, E> Apply<A, B> for Result<F, E> {
85 #[inline]
86 fn ap(self, fa: Result<A, E>) -> Result<B, E>
87 where
88 F: FnOnce(A) -> B,
89 {
90 match (self, fa) {
91 (Ok(f), Ok(a)) => Ok(f(a)),
92 (Err(e), _) => Err(e),
93 (_, Err(e)) => Err(e),
94 }
95 }
96}
97
98if_std! {
99 use std::boxed::Box;
100 use std::collections::*;
101 use std::hash::Hash;
102 use std::vec::Vec;
103
104 impl<F, A, B> Apply<A, B> for Box<F> {
105 #[inline]
106 fn ap(self, fa: Box<A>) -> Box<B>
107 where
108 F: FnOnce(A) -> B,
109 {
110 Box::new((*self)(*fa))
111 }
112 }
113
114 apply_iter!(Vec);
115 apply_iter!(LinkedList);
116 apply_iter!(VecDeque);
117 apply_iter!(BinaryHeap, Ord);
118 apply_iter!(BTreeSet, Ord);
119 apply_iter!(HashSet, Eq + Hash);
120
121 impl<F, A, B, K: Eq + Hash> Apply<A, B> for HashMap<K, F> {
122 #[inline]
123 fn ap(mut self, fa: HashMap<K, A>) -> HashMap<K, B>
124 where
125 F: FnOnce(A) -> B,
126 {
127 fa.into_iter()
128 .filter_map(|(k, a)| self.remove(&k).map(|f| (k, f(a))))
129 .collect()
130 }
131 }
132}