1use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
2use std::hash::{BuildHasher, Hash};
3
4use higher::Lift;
5
6pub trait Bind<A, B>: Lift<A, B> {
12 fn bind<F>(self, f: F) -> <Self as Lift<A, B>>::Target1
14 where
15 F: Fn(A) -> <Self as Lift<A, B>>::Target1;
16}
17
18impl<A, B> Bind<A, B> for Option<A> {
19 fn bind<F>(self, f: F) -> <Self as Lift<A, B>>::Target1
20 where
21 F: Fn(A) -> <Self as Lift<A, B>>::Target1,
22 {
23 self.and_then(f)
24 }
25}
26
27impl<A, B, E> Bind<A, B> for Result<A, E> {
28 fn bind<F>(self, f: F) -> <Self as Lift<A, B>>::Target1
29 where
30 F: Fn(A) -> <Self as Lift<A, B>>::Target1,
31 {
32 self.and_then(f)
33 }
34}
35
36impl<A, B> Bind<A, B> for Vec<A> {
37 fn bind<F>(self, f: F) -> <Self as Lift<A, B>>::Target1
38 where
39 F: Fn(A) -> <Self as Lift<A, B>>::Target1,
40 {
41 self.into_iter().flat_map(|v| f(v).into_iter()).collect()
42 }
43}
44
45impl<A, B> Bind<A, B> for VecDeque<A> {
46 fn bind<F>(self, f: F) -> <Self as Lift<A, B>>::Target1
47 where
48 F: Fn(A) -> <Self as Lift<A, B>>::Target1,
49 {
50 self.into_iter().flat_map(|v| f(v).into_iter()).collect()
51 }
52}
53
54impl<A, B> Bind<A, B> for LinkedList<A> {
55 fn bind<F>(self, f: F) -> <Self as Lift<A, B>>::Target1
56 where
57 F: Fn(A) -> <Self as Lift<A, B>>::Target1,
58 {
59 self.into_iter().flat_map(|v| f(v).into_iter()).collect()
60 }
61}
62
63impl<A, B> Bind<A, B> for BinaryHeap<A>
64where
65 A: Ord,
66 B: Ord,
67{
68 fn bind<F>(self, f: F) -> <Self as Lift<A, B>>::Target1
69 where
70 F: Fn(A) -> <Self as Lift<A, B>>::Target1,
71 {
72 self.into_iter().flat_map(|v| f(v).into_iter()).collect()
73 }
74}
75
76impl<A, B> Bind<A, B> for BTreeSet<A>
77where
78 A: Ord,
79 B: Ord,
80{
81 fn bind<F>(self, f: F) -> <Self as Lift<A, B>>::Target1
82 where
83 F: Fn(A) -> <Self as Lift<A, B>>::Target1,
84 {
85 self.into_iter().flat_map(|v| f(v).into_iter()).collect()
86 }
87}
88
89impl<A, B, S> Bind<A, B> for HashSet<A, S>
90where
91 A: Hash + Eq,
92 B: Hash + Eq,
93 S: BuildHasher + Default,
94{
95 fn bind<F>(self, f: F) -> <Self as Lift<A, B>>::Target1
96 where
97 F: Fn(A) -> <Self as Lift<A, B>>::Target1,
98 {
99 self.into_iter().flat_map(|v| f(v).into_iter()).collect()
100 }
101}
102
103impl<A, B, C, D, S> Bind<(A, B), (C, D)> for HashMap<A, B, S>
104where
105 A: Hash + Eq,
106 B: Hash + Eq,
107 C: Hash + Eq,
108 D: Hash + Eq,
109 S: BuildHasher + Default,
110{
111 fn bind<F>(self, f: F) -> <Self as Lift<(A, B), (C, D)>>::Target1
112 where
113 F: Fn((A, B)) -> <Self as Lift<(A, B), (C, D)>>::Target1,
114 {
115 self.into_iter().flat_map(|v| f(v).into_iter()).collect()
116 }
117}
118
119impl<A, B, C, D> Bind<(A, B), (C, D)> for BTreeMap<A, B>
120where
121 A: Ord,
122 B: Ord,
123 C: Ord,
124 D: Ord,
125{
126 fn bind<F>(self, f: F) -> <Self as Lift<(A, B), (C, D)>>::Target1
127 where
128 F: Fn((A, B)) -> <Self as Lift<(A, B), (C, D)>>::Target1,
129 {
130 self.into_iter().flat_map(|v| f(v).into_iter()).collect()
131 }
132}
133
134#[cfg(test)]
135mod test {
136 use super::*;
137 use crate::Pure;
138 use proptest::collection::vec;
139 use proptest::num::u8;
140 use proptest::proptest;
141
142 #[test]
143 fn bind_vec() {
144 let v = vec![1, 2, 3];
145 let o = v.bind(|i| vec![i, i + 1]);
146 assert_eq!(vec![1, 2, 2, 3, 3, 4], o);
147 }
148
149 proptest! {
150 #[test]
151 fn identity(v in vec(u8::ANY, 0..1000)) {
152 let orig = v.clone();
153 let result = v.bind(Pure::pure);
154 assert_eq!(orig, result);
155 }
156 }
157}