scsys_traits/
hkt.rs

1/*
2    Appellation: hkt <module>
3    Contrib: @FL03
4*/
5
6pub 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; // Current Type
21        type T; // Type C swapped with U
22    }
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
62/*
63 *************  Implementations  *************
64*/
65macro_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}