scsys_core/cont/traits/
hkt.rs1#[allow(clippy::upper_case_acronyms)]
7pub trait HKT<T> {
9 type Cont<_T>;
10}
11
12pub trait Functor<T>: HKT<T> {
15 fn fmap<F, U>(&self, f: F) -> Self::Cont<U>
16 where
17 F: Fn(&T) -> U;
18}
19
20macro_rules! hkt {
24 (@impl $($t:ident)::*<$T:ident>) => {
25 impl<$T> HKT<$T> for $($t)::*<$T> {
26 type Cont<_T> = $($t)::*<_T>;
27 }
28 };
29 (
30 $(
31 $($t:ident)::*<$T:ident>
32 ),* $(,)?
33 ) => {
34 $(
35 hkt!(@impl $($t)::*<$T>);
36 )*
37 };
38}
39
40hkt! {
41 core::option::Option<T>
42}
43
44#[cfg(feature = "alloc")]
45hkt! {
46 alloc::vec::Vec<T>,
47 alloc::boxed::Box<T>,
48 alloc::rc::Rc<T>,
49 alloc::rc::Weak<T>,
50 alloc::sync::Arc<T>,
51 alloc::collections::BinaryHeap<T>,
52 alloc::collections::BTreeSet<T>,
53 alloc::collections::LinkedList<T>,
54 alloc::collections::VecDeque<T>,
55}
56
57#[cfg(feature = "std")]
58hkt! {
59 std::cell::Cell<T>,
60 std::cell::OnceCell<T>,
61 std::cell::RefCell<T>,
62 std::sync::Mutex<T>,
63 std::sync::RwLock<T>,
64 std::sync::LazyLock<T>,
65 std::collections::HashSet<V>,
66}
67
68#[cfg(feature = "alloc")]
69impl<K, V> HKT<V> for alloc::collections::BTreeMap<K, V> {
70 type Cont<U> = alloc::collections::BTreeMap<K, U>;
71}
72
73#[cfg(feature = "std")]
74impl<K, V> HKT<V> for std::collections::HashMap<K, V> {
75 type Cont<U> = std::collections::HashMap<K, U>;
76}
77
78impl<T> Functor<T> for Option<T> {
79 fn fmap<F, U>(&self, f: F) -> Self::Cont<U>
80 where
81 F: Fn(&T) -> U,
82 {
83 self.as_ref().map(f)
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[test]
92 fn test_option() {
93 let opt = Some(42u8);
94 let opt2 = opt.fmap(|&x| x as usize + 1);
95 assert_eq!(opt2, Some(43_usize));
96 }
97}