scsys_core/hkt/
applicative.rs1pub trait HKT<U> {
10 type C; type T; }
13
14pub trait Functor<U>: HKT<U> {
15 fn fmap<F>(&self, f: F) -> Self::T
16 where
17 F: Fn(&Self::C) -> U;
18}
19
20pub trait Applicative<U>: Functor<U> {
21 fn pure_(value: U) -> Self::T
22 where
23 Self: HKT<U, C = U>;
24 fn seq<F>(&self, fs: <Self as HKT<F>>::T) -> <Self as HKT<U>>::T
25 where
26 F: Fn(&<Self as HKT<U>>::C) -> U,
27 Self: HKT<F>;
28}
29
30pub trait Monad<U>: Applicative<U> {
31 fn return_(x: U) -> Self::T
32 where
33 Self: HKT<U, C = U>,
34 {
35 Self::pure_(x)
36 }
37
38 fn bind<F>(&self, fs: F) -> Self::T
39 where
40 F: FnMut(&Self::C) -> Self::T;
41
42 fn join<T>(&self) -> T
43 where
44 Self: HKT<U, T = T, C = T>,
45 T: Clone,
46 {
47 self.bind(|x| x.clone())
48 }
49}
50
51#[macro_export]
55macro_rules! hkt {
56 ($($($p:ident)::*),* $(,)?) => {
57 $(
58 $crate::hkt!(@impl $($p)::*);
59 )*
60 };
61 (@impl $($p:ident)::*) => {
62 impl<T, U> HKT<U> for $($p)::*<T> {
63 type C = T;
64 type T = $($p)::*<U>;
65 }
66 };
67}
68
69#[allow(unused_macros)]
70macro_rules! functor {
71 ($($($p:ident)::*),* $(,)?) => {
72 $(
73 functor!(@impl $($p)::*);
74 )*
75 };
76 (@impl $($p:ident)::*) => {
77 impl<T, U> Functor<U> for $($p)::*<T> {
78 fn fmap<F>(&self, f: F) -> $($p)::*<U>
79 where
80 F: Fn(&T) -> U,
81 {
82 $($p)::*::new(f(self))
83 }
84 }
85 };
86}
87
88#[allow(unused_macros)]
89macro_rules! applicative {
90 ($($($p:ident)::*),* $(,)?) => {
91 $(
92 applicative!(@impl $($p)::*);
93 )*
94 };
95 (@impl $($p:ident)::*) => {
96 impl<T, U> Applicative<U> for $($p)::*<T> {
97 fn pure_(value: U) -> Self::T {
98 $($p)::*::new(value)
99 }
100
101 fn seq<F>(&self, fs: <Self as HKT<F>>::T) -> $($p)::*<U>
102 where
103 F: Fn(&<Self as HKT<U>>::C) -> U,
104 {
105 let v = fs(self);
106 $($p)::*::new(v)
107 }
108 }
109 };
110}
111
112#[allow(unused_macros)]
113macro_rules! monad {
114 ($($($p:ident)::*),* $(,)?) => {
115 $(
116 monad!(@impl $($p)::*);
117 )*
118 };
119 (@impl $($p:ident)::*) => {
120 impl<T, U> Monad<U> for $($p)::*<T> {
121 fn bind<F>(&self, mut fs: F) -> $($p)::*<U>
122 where
123 F: FnMut(&T) -> $($p)::*<U>,
124 {
125 fs(self)
126 }
127 }
128 };
129}
130
131hkt!(core::option::Option);
132
133#[cfg(feature = "alloc")]
134hkt!(
135 alloc::sync::Arc,
136 alloc::boxed::Box,
137 alloc::rc::Rc,
138 alloc::vec::Vec
139);
140
141#[cfg(feature = "alloc")]
142functor!(alloc::sync::Arc, alloc::boxed::Box, alloc::rc::Rc);
143
144#[cfg(feature = "alloc")]
145applicative!(alloc::sync::Arc, alloc::boxed::Box, alloc::rc::Rc);
146
147#[cfg(feature = "alloc")]
148monad!(alloc::sync::Arc, alloc::boxed::Box, alloc::rc::Rc);
149
150impl<T, U> Functor<U> for Option<T> {
151 fn fmap<F>(&self, f: F) -> Option<U>
152 where
153 F: Fn(&T) -> U,
154 {
155 if let Some(value) = self {
156 return Some(f(value));
157 }
158 None
159 }
160}
161
162#[cfg(feature = "alloc")]
163impl<T, U> Functor<U> for Vec<T> {
164 fn fmap<F>(&self, f: F) -> Vec<U>
165 where
166 F: Fn(&T) -> U,
167 {
168 let mut result = Vec::with_capacity(self.len());
169 for value in self {
170 result.push(f(value));
171 }
172 result
173 }
174}
175
176impl<T, U> Applicative<U> for core::option::Option<T> {
177 fn pure_(value: U) -> Self::T {
178 Some(value)
179 }
180
181 fn seq<F>(&self, fs: <Self as HKT<F>>::T) -> Option<U>
182 where
183 F: Fn(&T) -> U,
184 {
185 match *self {
186 Some(ref value) => fs.map(|f| f(value)),
187 None => None,
188 }
189 }
190}
191
192#[cfg(feature = "alloc")]
193impl<T, U> Applicative<U> for alloc::vec::Vec<T> {
194 fn pure_(value: U) -> Self::T {
195 vec![value]
196 }
197
198 fn seq<F>(&self, fs: <Self as HKT<F>>::T) -> alloc::vec::Vec<U>
199 where
200 F: Fn(&T) -> U,
201 {
202 let mut result = alloc::vec::Vec::new();
203 for (i, f) in fs.into_iter().enumerate() {
204 let v = (f)(&self[i]);
205 result.push(v)
206 }
207 result
208 }
209}
210
211impl<T, U> Monad<U> for core::option::Option<T> {
212 fn bind<F>(&self, mut fs: F) -> core::option::Option<U>
213 where
214 F: FnMut(&T) -> core::option::Option<U>,
215 {
216 match self {
217 Some(x) => fs(x),
218 None => None,
219 }
220 }
221}
222
223#[cfg(feature = "alloc")]
224impl<T, U> Monad<U> for alloc::vec::Vec<T> {
225 fn bind<F>(&self, mut fs: F) -> Vec<U>
226 where
227 F: FnMut(&T) -> alloc::vec::Vec<U>,
228 {
229 let mut v = alloc::vec::Vec::new();
230 for x in self {
231 v.extend(fs(x));
232 }
233 v
234 }
235}
236
237#[allow(unused_imports)]
238#[cfg(test)]
239mod tests {
240 use super::*;
241
242 #[cfg(feature = "alloc")]
243 #[test]
244 fn test_hkt_vec() {
245 let v = Vec::from_iter(0..9);
246 let v2 = v.fmap(|x| (x + 1).to_string());
247 assert_eq!(v2, ["1", "2", "3", "4", "5", "6", "7", "8", "9"]);
248
249 let v = Vec::return_(0);
250 let v2 = v.bind(|x| vec![x + 1]);
251 assert_eq!(v2, [1]);
252 }
253}