scsys_core/hkt/
applicative.rs

1/*
2    Appellation: applicative <mod>
3    Contrib: FL03 <jo3mccain@icloud.com>
4*/
5//! # Applicative
6//!
7//!
8
9pub trait HKT<U> {
10    type C; // Current Type
11    type T; // Type C swapped with U
12}
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/*
52 ************* Implementations *************
53*/
54#[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}