1use std::collections::BTreeSet;
2use std::fmt;
3use std::hash::Hash;
4
5mod sealed {
7 pub enum Step<Req, A, R> {
8 Request(Req, A),
9 Fork(A, A),
11 Return(R),
12 }
13
14 impl<Req, A, R> Step<Req, A, R> {
15 fn map_cont<B>(self, f: impl Fn(A) -> B) -> Step<Req, B, R> {
16 match self {
17 Step::Request(req, a) => Step::Request(req, f(a)),
18 Step::Fork(x, y) => Step::Fork(f(x), f(y)),
19 Step::Return(r) => Step::Return(r),
20 }
21 }
22
23 fn map_ret<S>(self, f: impl FnOnce(R) -> S) -> Step<Req, A, S> {
24 match self {
25 Step::Request(req, a) => Step::Request(req, a),
26 Step::Fork(x, y) => Step::Fork(x, y),
27 Step::Return(r) => Step::Return(f(r)),
28 }
29 }
30 }
31
32 pub trait LazySet<Req, Res>: Clone {
33 type Item;
34 fn step(self, res: Option<Res>) -> Step<Req, Self, Option<Self::Item>>;
35 }
36
37 #[derive(Clone)]
38 pub struct One<T>(pub(super) T);
39
40 impl<Req, Res, T: Clone> LazySet<Req, Res> for One<T> {
41 type Item = T;
42 fn step(self, res: Option<Res>) -> Step<Req, Self, Option<Self::Item>> {
43 assert!(res.is_none());
44 Step::Return(Some(self.0))
45 }
46 }
47
48 impl<Req, Res, T: Clone> LazySet<Req, Res> for Option<T> {
49 type Item = T;
50 fn step(self, res: Option<Res>) -> Step<Req, Self, Option<Self::Item>> {
51 assert!(res.is_none());
52 Step::Return(self)
53 }
54 }
55
56 #[derive(Clone)]
57 pub enum Request<Req> {
58 Start(Req),
59 Complete,
60 }
61
62 impl<Req: Clone, Res> LazySet<Req, Res> for Request<Req> {
63 type Item = Res;
64 fn step(self, res: Option<Res>) -> Step<Req, Self, Option<Self::Item>> {
65 match self {
66 Request::Start(req) => {
67 assert!(res.is_none());
68 Step::Request(req, Request::Complete)
69 }
70 Request::Complete => Step::Return(Some(res.unwrap())),
71 }
72 }
73 }
74
75 #[derive(Clone)]
76 pub enum Union<A, B> {
77 Start(A, B),
78 JustA(A),
79 JustB(B),
80 }
81
82 impl<Req, Res, A, B, T> LazySet<Req, Res> for Union<A, B>
83 where
84 A: LazySet<Req, Res, Item = T>,
85 B: LazySet<Req, Res, Item = T>,
86 {
87 type Item = T;
88 fn step(self, res: Option<Res>) -> Step<Req, Self, Option<Self::Item>> {
89 match self {
90 Union::Start(a, b) => {
91 assert!(res.is_none());
92 Step::Fork(Union::JustA(a), Union::JustB(b))
93 }
94 Union::JustA(a) => a.step(res).map_cont(Union::JustA),
95 Union::JustB(b) => b.step(res).map_cont(Union::JustB),
96 }
97 }
98 }
99
100 #[derive(Clone)]
101 pub struct Map<A, F>(pub(super) A, pub(super) F);
102
103 impl<Req, Res, A, F, T> LazySet<Req, Res> for Map<A, F>
104 where
105 A: LazySet<Req, Res>,
106 F: FnOnce(A::Item) -> T + Clone,
107 {
108 type Item = T;
109 fn step(self, res: Option<Res>) -> Step<Req, Self, Option<Self::Item>> {
110 let Map(a, f) = self;
111 a.step(res)
112 .map_cont(|a| Map(a, f.clone()))
113 .map_ret(|r| r.map(f))
114 }
115 }
116
117 #[derive(Clone)]
118 pub enum FlatMap<A, B, F> {
119 Start(A, F),
120 Then(B),
121 }
122
123 impl<Req, Res, A, B, F> LazySet<Req, Res> for FlatMap<A, B, F>
124 where
125 A: LazySet<Req, Res>,
126 B: LazySet<Req, Res>,
127 F: FnOnce(A::Item) -> B + Clone,
128 {
129 type Item = B::Item;
130 fn step(self, res: Option<Res>) -> Step<Req, Self, Option<Self::Item>> {
131 match self {
132 FlatMap::Start(a, f) => match a.step(res) {
133 Step::Request(req, a) => Step::Request(req, FlatMap::Start(a, f)),
134 Step::Fork(x, y) => {
135 Step::Fork(FlatMap::Start(x, f.clone()), FlatMap::Start(y, f))
136 }
137 Step::Return(None) => Step::Return(None),
138 Step::Return(Some(r)) => f(r).step(None).map_cont(FlatMap::Then),
139 },
140 FlatMap::Then(b) => b.step(res).map_cont(FlatMap::Then),
141 }
142 }
143 }
144}
145
146pub trait LazySet<Req, Res>: sealed::LazySet<Req, Res> {
149 fn union<B: LazySet<Req, Res, Item = Self::Item>>(self, b: B) -> sealed::Union<Self, B> {
150 sealed::Union::Start(self, b)
151 }
152
153 fn map<F: FnOnce(Self::Item) -> T, T>(self, f: F) -> sealed::Map<Self, F> {
154 sealed::Map(self, f)
155 }
156
157 fn flat_map<B: LazySet<Req, Res>, F: FnOnce(Self::Item) -> B>(
158 self,
159 f: F,
160 ) -> sealed::FlatMap<Self, B, F> {
161 sealed::FlatMap::Start(self, f)
162 }
163
164 fn run(
165 self,
166 handle: &mut impl FnMut(Req, Self) -> BTreeSet<Res>,
167 res: Option<Res>,
168 ) -> BTreeSet<Self::Item>
169 where
170 Res: Ord,
171 Self::Item: Ord,
172 {
173 let mut output = BTreeSet::new();
174 match self.step(res) {
175 sealed::Step::Request(req, a) => {
176 for res in handle(req, a.clone()) {
177 output.extend(a.clone().run(handle, Some(res)));
178 }
179 }
180 sealed::Step::Fork(a, b) => {
181 output.extend(a.run(handle, None));
182 output.extend(b.run(handle, None));
183 }
184 sealed::Step::Return(v) => output.extend(v),
185 }
186 output
187 }
188}
189
190impl<Req, Res, A: sealed::LazySet<Req, Res>> LazySet<Req, Res> for A {}
191
192pub fn one<T>(x: T) -> sealed::One<T> {
193 sealed::One(x)
194}
195
196pub fn request<Req>(req: Req) -> sealed::Request<Req> {
197 sealed::Request::Start(req)
198}
199
200#[derive(Clone)]
201pub struct Call<T>(pub T);
202
203pub fn call<T>(x: T) -> sealed::Request<Call<T>> {
204 request(Call(x))
205}
206
207pub fn to_eager<K, V, A>(
210 lazy_f: impl FnOnce(K) -> A + Clone,
211) -> impl FnOnce(&mut dyn FnMut(K) -> BTreeSet<V>, K) -> BTreeSet<V> + Clone
212where
213 K: Copy + Eq + Hash + fmt::Debug,
214 V: Clone + Ord + fmt::Debug,
215 A: LazySet<Call<K>, V, Item = V>,
216{
217 move |f, k| lazy_f(k).run(&mut |Call(k), _| f(k), None)
218}
219
220pub mod depth_first {
222 use super::*;
223
224 use std::collections::{hash_map::Entry, HashMap};
225
226 struct CallState<K, V, A> {
227 returns: Vec<(K, A)>,
230 results: BTreeSet<V>,
231 }
232
233 struct MemoState<K, V, A, F> {
234 calls: HashMap<K, CallState<K, V, A>>,
235 f: F,
236 }
237
238 pub fn memoize<K, V, A>(f: impl FnOnce(K) -> A + Clone) -> impl FnMut(K) -> BTreeSet<V>
239 where
240 K: Copy + Ord + Hash + fmt::Debug,
241 V: Clone + Ord + fmt::Debug,
242 A: LazySet<Call<K>, V, Item = V>,
243 {
244 let mut state = MemoState {
245 calls: HashMap::new(),
246 f,
247 };
248 move |k| match state.calls.entry(k) {
249 Entry::Occupied(entry) => entry.get().results.clone(),
253
254 Entry::Vacant(entry) => {
256 entry.insert(CallState {
257 returns: Default::default(),
258 results: Default::default(),
259 });
260 let f = state.f.clone();
261 state.run(k, f(k), None);
262 state.calls[&k].results.clone()
263 }
264 }
265 }
266
267 impl<K, V, A, F> MemoState<K, V, A, F>
268 where
269 K: Copy + Eq + Hash + fmt::Debug,
270 V: Clone + Ord + fmt::Debug,
271 A: LazySet<Call<K>, V, Item = V>,
272 F: FnOnce(K) -> A + Clone,
273 {
274 fn run(&mut self, current: K, a: A, res: Option<V>) {
276 match a.step(res) {
277 sealed::Step::Request(Call(k), a) => match self.calls.entry(k) {
279 Entry::Occupied(entry) => {
281 let call = entry.into_mut();
282 call.returns.push((current, a.clone()));
285 {
286 for v in call.results.clone() {
288 self.run(current, a.clone(), Some(v));
289 }
290 }
291 }
292
293 Entry::Vacant(entry) => {
295 let call = entry.insert(CallState {
296 returns: Default::default(),
297 results: Default::default(),
298 });
299 call.returns.push((current, a.clone()));
302 let f = self.f.clone();
303 self.run(k, f(k), None);
304 }
305 },
306 sealed::Step::Fork(a, b) => {
307 self.run(current, a, None);
308 self.run(current, b, None);
309 }
310 sealed::Step::Return(None) => {}
311 sealed::Step::Return(Some(v)) => {
312 let call = self.calls.get_mut(¤t).unwrap();
313 if call.results.insert(v.clone()) {
314 for (caller, ret) in call.returns.clone() {
316 self.run(caller, ret, Some(v.clone()));
317 }
318 }
319 }
320 }
321 }
322 }
323}