1pub trait HKT {
7 type C<A>;
8}
9
10pub trait Functor<T>: HKT {
11 fn fmap<F, Z>(&self, f: F) -> Self::C<Z>
12 where
13 F: Fn(&Self::C<T>) -> Self::C<Z>;
14}
15#[doc(hidden)]
16#[allow(unused)]
17mod old {
18
19 pub trait HKT<U> {
20 type C; type T; }
23
24 pub trait Functor<U>: HKT<U> {
25 fn fmap<F>(&self, f: F) -> Self::T
26 where
27 F: Fn(&Self::C) -> U;
28 }
29
30 pub trait Applicative<U>: Functor<U> {
31 fn pure_(value: U) -> Self::T
32 where
33 Self: HKT<U, C = U>;
34 fn seq<F>(&self, fs: <Self as HKT<F>>::T) -> <Self as HKT<U>>::T
35 where
36 F: Fn(&<Self as HKT<U>>::C) -> U,
37 Self: HKT<F>;
38 }
39
40 pub trait Monad<U>: Applicative<U> {
41 fn return_(x: U) -> Self::T
42 where
43 Self: HKT<U, C = U>,
44 {
45 Self::pure_(x)
46 }
47
48 fn bind<F>(&self, fs: F) -> Self::T
49 where
50 F: FnMut(&Self::C) -> Self::T;
51
52 fn join<T>(&self) -> T
53 where
54 Self: HKT<U, T = T, C = T>,
55 T: Clone,
56 {
57 self.bind(|x| x.clone())
58 }
59 }
60}
61
62macro_rules! hkt {
66 ($($($t:ident)::*),*) => {
67 $(
68 hkt!(@impl $($t)::*);
69 )*
70 };
71 (@impl $($t:ident)::*) => {
72 impl<T> HKT for $($t)::*<T> {
73 type C<A> = $($t)::*<A>;
74 }
75 };
76}
77
78macro_rules! functor {
79 ($($($t:ident)::*),*) => {
80 $(
81 functor!(@impl $($t)::*);
82 )*
83 };
84 (@impl $($t:ident)::*) => {
85 impl<T> Functor<T> for $($t)::*<T> {
86 fn fmap<F, Z>(&self, f: F) -> Self::C<Z>
87 where
88 F: Fn(&Self::C<T>) -> Self::C<Z> {
89 f(self)
90 }
91 }
92 };
93}
94
95hkt!(core::option::Option);
96functor!(core::option::Option);
97
98#[cfg(feature = "alloc")]
99hkt! {
100 alloc::collections::VecDeque,
101 alloc::collections::LinkedList,
102 alloc::boxed::Box,
103 alloc::rc::Rc,
104 alloc::sync::Arc,
105 alloc::vec::Vec
106}
107
108#[cfg(feature = "alloc")]
109functor! {
110 alloc::collections::VecDeque,
111 alloc::collections::LinkedList,
112 alloc::boxed::Box,
113 alloc::rc::Rc,
114 alloc::sync::Arc,
115 alloc::vec::Vec
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121 use num_traits::FromPrimitive;
122
123 #[test]
124 fn test_option() {
125 let opt = Some(42u8);
126 let opt2 = opt.fmap(|x| x.map(|i| usize::from_u8(i).unwrap() + 1));
127 assert_eq!(opt2, Some(43usize));
128 }
129}