1use super::functions::*;
6use std::collections::HashMap;
7
8#[allow(dead_code)]
10pub struct OptionComonad<T: Clone> {
11 value: Option<T>,
12 default: T,
13}
14impl<T: Clone> OptionComonad<T> {
15 #[allow(dead_code)]
16 pub fn new(value: Option<T>, default: T) -> Self {
17 Self { value, default }
18 }
19 #[allow(dead_code)]
21 pub fn extract(&self) -> T {
22 self.value.clone().unwrap_or_else(|| self.default.clone())
23 }
24 #[allow(dead_code)]
26 pub fn extend<B: Clone>(&self, f: impl Fn(&OptionComonad<T>) -> B) -> Option<B> {
27 Some(f(self))
28 }
29 #[allow(dead_code)]
30 pub fn duplicate_as_pair(&self) -> (T, Option<T>) {
31 (self.default.clone(), self.value.clone())
32 }
33}
34#[allow(dead_code)]
38pub struct OptionMemo<K: std::hash::Hash + Eq, V: Clone> {
39 cache: std::collections::HashMap<K, Option<V>>,
40}
41impl<K: std::hash::Hash + Eq, V: Clone> OptionMemo<K, V> {
42 #[allow(dead_code)]
44 pub fn new() -> Self {
45 Self {
46 cache: std::collections::HashMap::new(),
47 }
48 }
49 #[allow(dead_code)]
51 pub fn get_or_compute(&mut self, key: K, f: impl FnOnce(&K) -> Option<V>) -> Option<V>
52 where
53 K: Clone,
54 {
55 if let Some(v) = self.cache.get(&key) {
56 return v.clone();
57 }
58 let v = f(&key);
59 self.cache.insert(key, v.clone());
60 v
61 }
62 #[allow(dead_code)]
64 pub fn clear(&mut self) {
65 self.cache.clear();
66 }
67 #[allow(dead_code)]
69 pub fn len(&self) -> usize {
70 self.cache.len()
71 }
72 #[allow(dead_code)]
74 pub fn is_empty(&self) -> bool {
75 self.cache.is_empty()
76 }
77}
78#[allow(dead_code)]
80pub struct OptionIter<T>(pub(super) Option<T>);
81impl<T> OptionIter<T> {
82 #[allow(dead_code)]
84 pub fn new(opt: Option<T>) -> Self {
85 Self(opt)
86 }
87}
88#[allow(dead_code)]
90pub struct OptionFunctor<T>(pub Option<T>);
91impl<T> OptionFunctor<T> {
92 #[allow(dead_code)]
93 pub fn new(v: Option<T>) -> Self {
94 Self(v)
95 }
96 #[allow(dead_code)]
97 pub fn fmap<U>(self, f: impl FnOnce(T) -> U) -> OptionFunctor<U> {
98 OptionFunctor(self.0.map(f))
99 }
100 #[allow(dead_code)]
101 pub fn fmap_id(self) -> OptionFunctor<T> {
102 OptionFunctor(self.0)
103 }
104 #[allow(dead_code)]
105 pub fn inner(self) -> Option<T> {
106 self.0
107 }
108}
109#[allow(dead_code)]
111pub struct OptionApplicative;
112impl OptionApplicative {
113 #[allow(dead_code)]
114 pub fn pure<T>(v: T) -> Option<T> {
115 Some(v)
116 }
117 #[allow(dead_code)]
118 pub fn ap<A, B>(f: Option<impl FnOnce(A) -> B>, a: Option<A>) -> Option<B> {
119 match (f, a) {
120 (Some(func), Some(val)) => Some(func(val)),
121 _ => None,
122 }
123 }
124 #[allow(dead_code)]
125 pub fn lift_a2<A, B, C>(f: impl FnOnce(A, B) -> C, a: Option<A>, b: Option<B>) -> Option<C> {
126 match (a, b) {
127 (Some(x), Some(y)) => Some(f(x, y)),
128 _ => None,
129 }
130 }
131}
132#[derive(Debug, Clone, Default)]
137pub struct OptionCache<K: PartialEq, V> {
138 entries: Vec<(K, Option<V>)>,
139}
140impl<K: PartialEq, V: Clone> OptionCache<K, V> {
141 pub fn new() -> Self {
143 Self {
144 entries: Vec::new(),
145 }
146 }
147 pub fn get_or_insert_with(&mut self, key: K, compute: impl FnOnce() -> Option<V>) -> Option<V>
152 where
153 K: Clone,
154 {
155 if let Some(entry) = self.entries.iter().find(|(k, _)| k == &key) {
156 return entry.1.clone();
157 }
158 let value = compute();
159 self.entries.push((key, value.clone()));
160 value
161 }
162 pub fn insert(&mut self, key: K, value: Option<V>)
164 where
165 K: Clone,
166 V: Clone,
167 {
168 if let Some(entry) = self.entries.iter_mut().find(|(k, _)| k == &key) {
169 entry.1 = value;
170 } else {
171 self.entries.push((key, value));
172 }
173 }
174 pub fn get(&self, key: &K) -> Option<Option<&V>> {
176 self.entries
177 .iter()
178 .find(|(k, _)| k == key)
179 .map(|(_, v)| v.as_ref())
180 }
181 pub fn invalidate(&mut self, key: &K) {
183 self.entries.retain(|(k, _)| k != key);
184 }
185 pub fn clear(&mut self) {
187 self.entries.clear();
188 }
189 pub fn len(&self) -> usize {
191 self.entries.len()
192 }
193 pub fn is_empty(&self) -> bool {
195 self.entries.is_empty()
196 }
197}
198#[allow(dead_code)]
202pub struct OptionChain<T> {
203 value: Option<T>,
204}
205impl<T> OptionChain<T> {
206 #[allow(dead_code)]
208 pub fn from(opt: Option<T>) -> Self {
209 Self { value: opt }
210 }
211 #[allow(dead_code)]
213 pub fn of(v: T) -> Self {
214 Self { value: Some(v) }
215 }
216 #[allow(dead_code)]
218 pub fn empty() -> Self {
219 Self { value: None }
220 }
221 #[allow(dead_code)]
223 pub fn map<U>(self, f: impl FnOnce(T) -> U) -> OptionChain<U> {
224 OptionChain {
225 value: self.value.map(f),
226 }
227 }
228 #[allow(dead_code)]
230 pub fn flat_map<U>(self, f: impl FnOnce(T) -> Option<U>) -> OptionChain<U> {
231 OptionChain {
232 value: self.value.and_then(f),
233 }
234 }
235 #[allow(dead_code)]
237 pub fn filter(self, pred: impl FnOnce(&T) -> bool) -> Self {
238 Self {
239 value: self.value.filter(pred),
240 }
241 }
242 #[allow(dead_code)]
244 pub fn or_else(self, fallback: Option<T>) -> Self {
245 Self {
246 value: self.value.or(fallback),
247 }
248 }
249 #[allow(dead_code)]
251 pub fn get(self) -> Option<T> {
252 self.value
253 }
254 #[allow(dead_code)]
256 pub fn get_or(self, default: T) -> T {
257 self.value.unwrap_or(default)
258 }
259 #[allow(dead_code)]
261 pub fn is_present(&self) -> bool {
262 self.value.is_some()
263 }
264 #[allow(dead_code)]
266 pub fn peek(&self) -> Option<&T> {
267 self.value.as_ref()
268 }
269}
270#[allow(dead_code)]
272pub struct OptionWriter<T, W> {
273 value: Option<T>,
274 log: W,
275}
276impl<T, W: Default> OptionWriter<T, W> {
277 #[allow(dead_code)]
278 pub fn new(value: Option<T>, log: W) -> Self {
279 Self { value, log }
280 }
281 #[allow(dead_code)]
282 pub fn pure_some(value: T) -> Self {
283 Self {
284 value: Some(value),
285 log: W::default(),
286 }
287 }
288 #[allow(dead_code)]
289 pub fn none_with_log(log: W) -> Self {
290 Self { value: None, log }
291 }
292 #[allow(dead_code)]
293 pub fn is_some(&self) -> bool {
294 self.value.is_some()
295 }
296}
297#[allow(dead_code)]
299pub struct OptionResultBridge;
300impl OptionResultBridge {
301 #[allow(dead_code)]
303 pub fn to_result<T, E>(opt: Option<T>, err: E) -> Result<T, E> {
304 opt.ok_or(err)
305 }
306 #[allow(dead_code)]
308 pub fn to_result_with<T, E>(opt: Option<T>, f: impl FnOnce() -> E) -> Result<T, E> {
309 opt.ok_or_else(f)
310 }
311 #[allow(dead_code)]
313 pub fn from_result_ok<T, E>(r: Result<T, E>) -> Option<T> {
314 r.ok()
315 }
316 #[allow(dead_code)]
318 pub fn from_result_err<T, E>(r: Result<T, E>) -> Option<E> {
319 r.err()
320 }
321 #[allow(dead_code)]
323 pub fn transpose_result<T, E>(r: Result<Option<T>, E>) -> Option<Result<T, E>> {
324 match r {
325 Ok(Some(v)) => Some(Ok(v)),
326 Ok(None) => None,
327 Err(e) => Some(Err(e)),
328 }
329 }
330}
331#[allow(dead_code)]
333pub struct OptionProfunctor<A, B> {
334 run: Box<dyn Fn(A) -> Option<B>>,
335}
336impl<A: 'static, B: 'static> OptionProfunctor<A, B> {
337 #[allow(dead_code)]
338 pub fn new(f: impl Fn(A) -> Option<B> + 'static) -> Self {
339 Self { run: Box::new(f) }
340 }
341 #[allow(dead_code)]
342 pub fn apply(&self, a: A) -> Option<B> {
343 (self.run)(a)
344 }
345 #[allow(dead_code)]
346 pub fn dimap<C: 'static, D: 'static>(
347 self,
348 pre: impl Fn(C) -> A + 'static,
349 post: impl Fn(B) -> D + 'static,
350 ) -> OptionProfunctor<C, D> {
351 OptionProfunctor::new(move |c| (self.run)(pre(c)).map(|b| post(b)))
352 }
353}
354#[derive(Debug, Clone, Default)]
358pub struct OptionMap<K: PartialEq, V> {
359 entries: Vec<(K, Option<V>)>,
360}
361impl<K: PartialEq, V> OptionMap<K, V> {
362 pub fn new() -> Self {
364 Self {
365 entries: Vec::new(),
366 }
367 }
368 pub fn set(&mut self, key: K, value: Option<V>) {
370 if let Some(entry) = self.entries.iter_mut().find(|(k, _)| k == &key) {
371 entry.1 = value;
372 } else {
373 self.entries.push((key, value));
374 }
375 }
376 pub fn get(&self, key: &K) -> Option<&V> {
378 self.entries
379 .iter()
380 .find(|(k, _)| k == key)
381 .and_then(|(_, v)| v.as_ref())
382 }
383 pub fn contains_key(&self, key: &K) -> bool {
385 self.entries.iter().any(|(k, _)| k == key)
386 }
387 pub fn len(&self) -> usize {
389 self.entries.len()
390 }
391 pub fn is_empty(&self) -> bool {
393 self.entries.is_empty()
394 }
395 pub fn some_keys(&self) -> Vec<&K> {
397 self.entries
398 .iter()
399 .filter(|(_, v)| v.is_some())
400 .map(|(k, _)| k)
401 .collect()
402 }
403 pub fn none_keys(&self) -> Vec<&K> {
405 self.entries
406 .iter()
407 .filter(|(_, v)| v.is_none())
408 .map(|(k, _)| k)
409 .collect()
410 }
411 pub fn iter(&self) -> impl Iterator<Item = &(K, Option<V>)> {
413 self.entries.iter()
414 }
415}
416#[allow(dead_code)]
418pub struct OptionVec<T> {
419 pub(super) items: Vec<Option<T>>,
420}
421impl<T> OptionVec<T> {
422 #[allow(dead_code)]
424 pub fn new() -> Self {
425 Self { items: Vec::new() }
426 }
427 #[allow(dead_code)]
429 pub fn push(&mut self, item: Option<T>) {
430 self.items.push(item);
431 }
432 #[allow(dead_code)]
434 pub fn sequence(self) -> Option<Vec<T>> {
435 let mut result = Vec::with_capacity(self.items.len());
436 for item in self.items {
437 result.push(item?);
438 }
439 Some(result)
440 }
441 #[allow(dead_code)]
443 pub fn collect_some(self) -> Vec<T> {
444 self.items.into_iter().flatten().collect()
445 }
446 #[allow(dead_code)]
448 pub fn count_some(&self) -> usize {
449 self.items.iter().filter(|o| o.is_some()).count()
450 }
451 #[allow(dead_code)]
453 pub fn count_none(&self) -> usize {
454 self.items.iter().filter(|o| o.is_none()).count()
455 }
456 #[allow(dead_code)]
458 pub fn len(&self) -> usize {
459 self.items.len()
460 }
461 #[allow(dead_code)]
463 pub fn is_empty(&self) -> bool {
464 self.items.is_empty()
465 }
466 #[allow(dead_code)]
468 pub fn all_some(&self) -> bool {
469 self.items.iter().all(|o| o.is_some())
470 }
471 #[allow(dead_code)]
473 pub fn any_some(&self) -> bool {
474 self.items.iter().any(|o| o.is_some())
475 }
476}
477#[derive(Debug, Clone, PartialEq)]
479pub struct WeightedOption<T> {
480 pub weight: f64,
482 pub value: Option<T>,
484}
485impl<T> WeightedOption<T> {
486 pub fn some(weight: f64, value: T) -> Self {
488 Self {
489 weight,
490 value: Some(value),
491 }
492 }
493 pub fn none(weight: f64) -> Self {
495 Self {
496 weight,
497 value: None,
498 }
499 }
500 pub fn better(self, other: Self) -> Self {
502 if self.weight >= other.weight {
503 self
504 } else {
505 other
506 }
507 }
508}