rust_fp_categories/
bind.rs

1use std::rc::Rc;
2
3pub trait Bind {
4    type Elm;
5    type M<B>;
6
7    fn bind<B, F>(self, f: F) -> Self::M<B>
8    where
9        F: Fn(&Self::Elm) -> Self::M<B>;
10}
11
12macro_rules! bind_numeric_impl {
13    ($($t:ty)*) => ($(
14        impl Bind for $t {
15          type Elm = $t;
16          type M<U> = U;
17
18          fn bind<B, F>(self, f: F) -> Self::M<B>
19            where
20              F: Fn(&Self::Elm) -> Self::M<B>,
21          {
22            f(&self)
23          }
24        }
25    )*)
26}
27
28bind_numeric_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
29
30impl<A> Bind for Rc<A> {
31    type Elm = A;
32    type M<U> = Rc<U>;
33
34    fn bind<B, F>(self, f: F) -> Self::M<B>
35    where
36        F: FnOnce(&Self::Elm) -> Self::M<B>,
37    {
38        f(&self)
39    }
40}
41
42impl<A> Bind for Box<A> {
43    type Elm = A;
44    type M<U> = Box<U>;
45
46    fn bind<B, F>(self, f: F) -> Self::M<B>
47    where
48        F: FnOnce(&Self::Elm) -> Self::M<B>,
49    {
50        f(&self)
51    }
52}
53
54// ---
55
56impl<A> Bind for Option<A> {
57    type Elm = A;
58    type M<U> = Option<U>;
59
60    fn bind<B, F>(self, f: F) -> Self::M<B>
61    where
62        F: FnOnce(&Self::Elm) -> Self::M<B>,
63    {
64        self.and_then(|e| f(&e))
65    }
66}
67
68impl<A, E: Clone> Bind for Result<A, E> {
69    type Elm = A;
70    type M<U> = Result<U, E>;
71
72    fn bind<B, F>(self, f: F) -> Self::M<B>
73    where
74        F: FnOnce(&Self::Elm) -> Self::M<B>,
75    {
76        self.and_then(|e| f(&e))
77    }
78}
79
80impl<A> Bind for Vec<A> {
81    type Elm = A;
82    type M<U> = Vec<U>;
83
84    fn bind<B, F>(self, f: F) -> Self::M<B>
85    where
86        F: Fn(&Self::Elm) -> Self::M<B>,
87    {
88        self.iter().flat_map(f).collect()
89    }
90}