1pub trait Functor<F, T>
15where
16 F: FnOnce(Self::Elem) -> T,
17{
18 type Cont<U>: ?Sized;
19 type Elem;
20
21 fn apply(self, f: F) -> Self::Cont<T>;
22}
23
24pub trait FunctorIter<F, T>
25where
26 F: FnOnce(Self::Elem) -> T,
27{
28 type Cont<U>: ?Sized;
29 type Iter;
30 type Elem;
31
32 fn apply_all(self, f: F) -> Self::Cont<T>;
33}
34
35impl<U, V, F> Functor<F, V> for Option<U>
49where
50 F: FnOnce(U) -> V,
51{
52 type Cont<T> = Option<T>;
53 type Elem = U;
54
55 fn apply(self, f: F) -> Self::Cont<V> {
56 self.map(f)
57 }
58}
59
60impl<'a, U, V, F> Functor<F, V> for &'a Option<U>
61where
62 F: FnOnce(&U) -> V,
63{
64 type Cont<T> = Option<T>;
65 type Elem = &'a U;
66
67 fn apply(self, f: F) -> Self::Cont<V> {
68 self.as_ref().map(|x| f(x))
69 }
70}
71
72impl<F, X, Y, S, I> FunctorIter<F, Y> for S
73where
74 S: IntoIterator<Item = X, IntoIter = I>,
75 F: FnMut(X) -> Y,
76 I: Iterator<Item = X>,
77{
78 type Cont<U> = core::iter::Map<<S as IntoIterator>::IntoIter, F>;
79 type Iter = I;
80 type Elem = X;
81
82 fn apply_all(self, f: F) -> Self::Cont<Y> {
83 self.into_iter().map(f)
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[test]
92 fn test_option() {
93 fn sample(input: u8) -> f32 {
94 input as f32 + 1.25
95 }
96 assert_eq! {
97 Some(42u8).apply(sample),
98 Some(43.25)
99 }
100 }
101}