scsys_core/hkt/
mod.rs

1/*
2    Appellation: hkt <mod>
3    Contrib: FL03 <jo3mccain@icloud.com>
4*/
5//! # Higher Kinded Types
6//!
7//!
8#[doc(inline)]
9pub use self::{applicative::*, functor::*, monad::*};
10
11mod applicative;
12mod functor;
13mod monad;
14
15pub(crate) mod prelude {
16    pub use super::applicative::Applicative;
17    pub use super::functor::Functor;
18    pub use super::monad::Monad;
19    pub use super::HKT;
20}
21
22pub(crate) mod containers {
23    pub(crate) use core::option::Option;
24
25    #[cfg(feature = "alloc")]
26    pub(crate) use alloc::{boxed::Box, rc::Rc, sync::Arc, vec::Vec};
27}
28
29pub trait HKT<U> {
30    type C; // Current Type
31    type T; // Type C swapped with U
32}
33
34#[macro_export]
35macro_rules! hkt {
36    ($($($p:ident)::*),* $(,)?) => {
37        $(
38            $crate::hkt!(@impl $($p)::*);
39        )*
40    };
41    (@impl $($p:ident)::*) => {
42        impl<T, U> HKT<U> for $($p)::*<T> {
43            type C = T;
44            type T = $($p)::*<U>;
45        }
46    };
47}
48
49hkt!(containers::Option);
50
51#[cfg(feature = "alloc")]
52hkt!(
53    containers::Arc,
54    containers::Box,
55    containers::Rc,
56    containers::Vec
57);
58
59#[allow(unused_imports)]
60#[cfg(test)]
61mod tests {
62    use super::*;
63
64    #[cfg(feature = "alloc")]
65    #[test]
66    fn test_hkt_vec() {
67        let v = Vec::from_iter(0..9);
68        let v2 = v.fmap(|x| (x + 1).to_string());
69        assert_eq!(v2, ["1", "2", "3", "4", "5", "6", "7", "8", "9"]);
70
71        let v = Vec::return_(0);
72        let v2 = v.bind(|x| vec![x + 1]);
73        assert_eq!(v2, [1]);
74    }
75}