1use crate::env_builder::{app, sort, var, EnvBuilder};
6use oxilean_kernel::{BinderInfo, Declaration, Environment, Level};
7use oxilean_kernel::{Expr, Name};
8
9use super::types::{OptionCache, OptionIter, OptionMap, OptionMemo, WeightedOption};
10
11pub fn build_option_env(env: &mut EnvBuilder) {
15 env.add_axiom(Name::from_str("Option"), sort(1));
16 env.add_axiom(Name::from_str("Option.none"), sort(1));
17 env.add_axiom(Name::from_str("Option.some"), sort(1));
18 env.add_axiom(Name::from_str("Option.rec"), sort(1));
19}
20pub fn build_option_getd(env: &mut EnvBuilder) {
24 env.add_axiom(Name::from_str("Option.getD"), sort(1));
25}
26pub fn build_option_map(env: &mut EnvBuilder) {
30 env.add_axiom(Name::from_str("Option.map"), sort(1));
31}
32pub fn build_option_bind(env: &mut EnvBuilder) {
36 env.add_axiom(Name::from_str("Option.bind"), sort(1));
37}
38pub fn build_option_filter(env: &mut EnvBuilder) {
40 env.add_axiom(Name::from_str("Option.filter"), sort(1));
41}
42pub fn build_full_option_env(env: &mut EnvBuilder) {
44 build_option_env(env);
45 build_option_getd(env);
46 build_option_map(env);
47 build_option_bind(env);
48 build_option_filter(env);
49 env.add_axiom(Name::from_str("Option.isSome"), sort(1));
50 env.add_axiom(Name::from_str("Option.isNone"), sort(1));
51 env.add_axiom(Name::from_str("Option.get!"), sort(1));
52 env.add_axiom(Name::from_str("Option.toList"), sort(1));
53 env.add_axiom(Name::from_str("Option.all"), sort(1));
54 env.add_axiom(Name::from_str("Option.any"), sort(1));
55 env.add_axiom(Name::from_str("Option.zip"), sort(1));
56 env.add_axiom(Name::from_str("Option.unzip"), sort(1));
57 env.add_axiom(Name::from_str("Option.sequence"), sort(1));
58}
59pub fn mk_some(x: Expr) -> Expr {
61 app(var("Option.some"), x)
62}
63pub fn mk_none() -> Expr {
65 var("Option.none")
66}
67pub fn mk_option_getd(opt: Expr, default: Expr) -> Expr {
69 app(app(var("Option.getD"), opt), default)
70}
71pub fn mk_option_map(f: Expr, opt: Expr) -> Expr {
73 app(app(var("Option.map"), f), opt)
74}
75pub fn mk_option_bind(opt: Expr, f: Expr) -> Expr {
77 app(app(var("Option.bind"), opt), f)
78}
79pub fn option_get_or_else<T, U>(opt: Option<T>, default: U, f: impl FnOnce(T) -> U) -> U {
81 match opt {
82 Some(x) => f(x),
83 None => default,
84 }
85}
86pub fn option_map<T, U>(opt: Option<T>, f: impl FnOnce(T) -> U) -> Option<U> {
88 opt.map(f)
89}
90pub fn option_bind<T, U>(opt: Option<T>, f: impl FnOnce(T) -> Option<U>) -> Option<U> {
92 opt.and_then(f)
93}
94pub fn option_ap<T, U>(f: Option<impl FnOnce(T) -> U>, a: Option<T>) -> Option<U> {
96 match (f, a) {
97 (Some(func), Some(val)) => Some(func(val)),
98 _ => None,
99 }
100}
101pub fn option_lift2<A, B, C>(f: impl FnOnce(A, B) -> C, a: Option<A>, b: Option<B>) -> Option<C> {
103 match (a, b) {
104 (Some(x), Some(y)) => Some(f(x, y)),
105 _ => None,
106 }
107}
108pub fn option_lift3<A, B, C, D>(
110 f: impl FnOnce(A, B, C) -> D,
111 a: Option<A>,
112 b: Option<B>,
113 c: Option<C>,
114) -> Option<D> {
115 match (a, b, c) {
116 (Some(x), Some(y), Some(z)) => Some(f(x, y, z)),
117 _ => None,
118 }
119}
120pub fn option_zip<A, B>(a: Option<A>, b: Option<B>) -> Option<(A, B)> {
122 match (a, b) {
123 (Some(x), Some(y)) => Some((x, y)),
124 _ => None,
125 }
126}
127pub fn option_unzip<A, B>(p: Option<(A, B)>) -> (Option<A>, Option<B>) {
129 match p {
130 Some((a, b)) => (Some(a), Some(b)),
131 None => (None, None),
132 }
133}
134pub fn option_join<T>(opt: Option<Option<T>>) -> Option<T> {
136 opt.flatten()
137}
138pub fn option_sequence<T>(opts: Vec<Option<T>>) -> Option<Vec<T>> {
140 let mut result = Vec::with_capacity(opts.len());
141 for opt in opts {
142 result.push(opt?);
143 }
144 Some(result)
145}
146pub fn option_traverse<A, B>(xs: &[A], f: impl Fn(&A) -> Option<B>) -> Option<Vec<B>> {
150 let mut result = Vec::with_capacity(xs.len());
151 for x in xs {
152 result.push(f(x)?);
153 }
154 Some(result)
155}
156pub fn option_first<T>(opts: impl IntoIterator<Item = Option<T>>) -> Option<T> {
158 opts.into_iter().flatten().next()
159}
160pub fn option_last<T>(opts: Vec<Option<T>>) -> Option<T> {
162 opts.into_iter().flatten().last()
163}
164pub fn option_catsome<T>(opts: impl IntoIterator<Item = Option<T>>) -> Vec<T> {
166 opts.into_iter().flatten().collect()
167}
168pub fn option_retry<T>(n: usize, mut f: impl FnMut() -> Option<T>) -> Option<T> {
170 for _ in 0..n {
171 if let Some(v) = f() {
172 return Some(v);
173 }
174 }
175 None
176}
177pub fn option_transpose<T, E>(opt: Option<Result<T, E>>) -> Result<Option<T>, E> {
179 match opt {
180 Some(Ok(v)) => Ok(Some(v)),
181 Some(Err(e)) => Err(e),
182 None => Ok(None),
183 }
184}
185pub fn option_combine<T: Clone>(
187 a: Option<T>,
188 b: Option<T>,
189 f: impl FnOnce(T, T) -> T,
190) -> Option<T> {
191 match (a, b) {
192 (Some(x), Some(y)) => Some(f(x, y)),
193 (Some(x), None) => Some(x),
194 (None, Some(y)) => Some(y),
195 (None, None) => None,
196 }
197}
198pub fn option_alt<T>(a: Option<T>, b: Option<T>) -> Option<T> {
200 a.or(b)
201}
202pub fn option_filter<T>(opt: Option<T>, pred: impl FnOnce(&T) -> bool) -> Option<T> {
204 opt.filter(pred)
205}
206pub fn option_ok_or<T, E>(opt: Option<T>, err: E) -> Result<T, E> {
208 opt.ok_or(err)
209}
210pub fn result_to_option<T, E>(r: Result<T, E>) -> Option<T> {
212 r.ok()
213}
214pub fn option_tap<T: Clone>(opt: &Option<T>, f: impl FnOnce(&T)) -> &Option<T> {
216 if let Some(ref v) = opt {
217 f(v);
218 }
219 opt
220}
221pub fn option_to_owned(opt: Option<&str>) -> Option<String> {
223 opt.map(|s| s.to_owned())
224}
225pub fn option_as_ref<T>(opt: &Option<T>) -> Option<&T> {
227 opt.as_ref()
228}
229pub fn option_partition<T>(opts: Vec<Option<T>>) -> (Vec<T>, usize) {
231 let mut somes = Vec::new();
232 let mut none_count = 0;
233 for opt in opts {
234 match opt {
235 Some(v) => somes.push(v),
236 None => none_count += 1,
237 }
238 }
239 (somes, none_count)
240}
241pub fn option_fold<T, U>(opt: Option<T>, init: U, f: impl FnOnce(U, T) -> U) -> U {
245 match opt {
246 Some(x) => f(init, x),
247 None => init,
248 }
249}
250pub fn option_unwrap_or_default<T: Default>(opt: Option<T>) -> T {
252 opt.unwrap_or_default()
253}
254pub fn option_count_some<T>(opts: impl IntoIterator<Item = Option<T>>) -> usize {
256 opts.into_iter().filter(|o| o.is_some()).count()
257}
258pub fn option_find<T>(candidates: Vec<T>, pred: impl Fn(&T) -> bool) -> Option<T> {
260 candidates.into_iter().find(|x| pred(x))
261}
262pub fn option_annotate<A: Clone, B>(xs: &[A], f: impl Fn(&A) -> Option<B>) -> Vec<(A, Option<B>)> {
264 xs.iter().map(|x| (x.clone(), f(x))).collect()
265}
266#[cfg(test)]
267mod tests {
268 use super::*;
269 #[test]
270 fn test_option_map() {
271 assert_eq!(option_map(Some(2u32), |x| x * 3), Some(6));
272 assert_eq!(option_map::<u32, u32>(None, |x| x * 3), None);
273 }
274 #[test]
275 fn test_option_bind() {
276 let f = |x: u32| if x > 2 { Some(x * 10) } else { None };
277 assert_eq!(option_bind(Some(5), f), Some(50));
278 assert_eq!(option_bind(Some(1), f), None);
279 assert_eq!(option_bind(None, f), None);
280 }
281 #[test]
282 fn test_option_lift2() {
283 let r = option_lift2(|a: u32, b: u32| a + b, Some(3), Some(4));
284 assert_eq!(r, Some(7));
285 let r2 = option_lift2(|a: u32, b: u32| a + b, None, Some(4));
286 assert_eq!(r2, None);
287 }
288 #[test]
289 fn test_option_zip() {
290 assert_eq!(option_zip(Some(1u32), Some("a")), Some((1, "a")));
291 assert_eq!(option_zip::<u32, &str>(None, Some("a")), None);
292 }
293 #[test]
294 fn test_option_unzip() {
295 let (a, b) = option_unzip(Some((1u32, 2u32)));
296 assert_eq!(a, Some(1));
297 assert_eq!(b, Some(2));
298 let (c, d) = option_unzip::<u32, u32>(None);
299 assert_eq!(c, None);
300 assert_eq!(d, None);
301 }
302 #[test]
303 fn test_option_sequence() {
304 let v = vec![Some(1u32), Some(2), Some(3)];
305 assert_eq!(option_sequence(v), Some(vec![1, 2, 3]));
306 let v2 = vec![Some(1u32), None, Some(3)];
307 assert_eq!(option_sequence(v2), None);
308 }
309 #[test]
310 fn test_option_traverse() {
311 let xs = vec![2u32, 4, 6];
312 let r = option_traverse(&xs, |x| if x % 2 == 0 { Some(x / 2) } else { None });
313 assert_eq!(r, Some(vec![1, 2, 3]));
314 let xs2 = vec![2u32, 3, 6];
315 let r2 = option_traverse(&xs2, |x| if x % 2 == 0 { Some(x / 2) } else { None });
316 assert_eq!(r2, None);
317 }
318 #[test]
319 fn test_option_catsome() {
320 let opts = vec![Some(1u32), None, Some(3), None, Some(5)];
321 assert_eq!(option_catsome(opts), vec![1, 3, 5]);
322 }
323 #[test]
324 fn test_option_retry() {
325 let mut count = 0u32;
326 let result = option_retry(5, || {
327 count += 1;
328 if count >= 3 {
329 Some(count)
330 } else {
331 None
332 }
333 });
334 assert_eq!(result, Some(3));
335 }
336 #[test]
337 fn test_option_combine() {
338 let r = option_combine(Some(3u32), Some(5), |a, b| a + b);
339 assert_eq!(r, Some(8));
340 let r2 = option_combine(Some(3u32), None, |a, b| a + b);
341 assert_eq!(r2, Some(3));
342 let r3 = option_combine::<u32>(None, None, |a, b| a + b);
343 assert_eq!(r3, None);
344 }
345 #[test]
346 fn test_option_partition() {
347 let opts = vec![Some(1u32), None, Some(3), None];
348 let (somes, none_count) = option_partition(opts);
349 assert_eq!(somes, vec![1, 3]);
350 assert_eq!(none_count, 2);
351 }
352 #[test]
353 fn test_option_fold() {
354 let r = option_fold(Some(5u32), 0u32, |acc, x| acc + x);
355 assert_eq!(r, 5);
356 let r2 = option_fold::<u32, u32>(None, 42, |acc, x| acc + x);
357 assert_eq!(r2, 42);
358 }
359 #[test]
360 fn test_option_first_last() {
361 let opts = vec![None, Some(2u32), Some(3)];
362 assert_eq!(option_first(opts.clone()), Some(2));
363 assert_eq!(option_last(opts), Some(3));
364 }
365 #[test]
366 fn test_option_map_struct() {
367 let mut map: OptionMap<&str, u32> = OptionMap::new();
368 map.set("a", Some(1));
369 map.set("b", None);
370 assert_eq!(map.get(&"a"), Some(&1));
371 assert_eq!(map.get(&"b"), None);
372 assert_eq!(map.some_keys(), vec![&"a"]);
373 assert_eq!(map.none_keys(), vec![&"b"]);
374 }
375 #[test]
376 fn test_option_join() {
377 let nested: Option<Option<u32>> = Some(Some(42));
378 assert_eq!(option_join(nested), Some(42));
379 let nested2: Option<Option<u32>> = Some(None);
380 assert_eq!(option_join(nested2), None);
381 }
382 #[test]
383 fn test_option_transpose() {
384 let r: Option<Result<u32, &str>> = Some(Ok(5));
385 assert_eq!(option_transpose(r), Ok(Some(5)));
386 let r2: Option<Result<u32, &str>> = Some(Err("err"));
387 assert!(option_transpose(r2).is_err());
388 let r3: Option<Result<u32, &str>> = None;
389 assert_eq!(option_transpose(r3), Ok(None));
390 }
391}
392#[allow(clippy::wrong_self_convention)]
397pub trait OptionExt<T> {
398 fn try_map<U, E>(self, f: impl FnOnce(T) -> Result<U, E>) -> Result<Option<U>, E>;
400 fn is_some_and(self, pred: impl FnOnce(&T) -> bool) -> bool;
402 fn is_none_or(self, pred: impl FnOnce(&T) -> bool) -> bool;
404 fn and_also(self, other: Option<T>) -> Option<(T, T)>;
406 fn inspect_opt(self, f: impl FnOnce(&T)) -> Self;
408 fn to_vec(self) -> Vec<T>;
410 fn expect_msg(self, msg: &str) -> T;
412}
413impl<T> OptionExt<T> for Option<T> {
414 fn try_map<U, E>(self, f: impl FnOnce(T) -> Result<U, E>) -> Result<Option<U>, E> {
415 match self {
416 Some(v) => f(v).map(Some),
417 None => Ok(None),
418 }
419 }
420 fn is_some_and(self, pred: impl FnOnce(&T) -> bool) -> bool {
421 match self {
422 Some(ref v) => pred(v),
423 None => false,
424 }
425 }
426 fn is_none_or(self, pred: impl FnOnce(&T) -> bool) -> bool {
427 match self {
428 Some(ref v) => pred(v),
429 None => true,
430 }
431 }
432 fn and_also(self, other: Option<T>) -> Option<(T, T)> {
433 match (self, other) {
434 (Some(a), Some(b)) => Some((a, b)),
435 _ => None,
436 }
437 }
438 fn inspect_opt(self, f: impl FnOnce(&T)) -> Self {
439 if let Some(ref v) = self {
440 f(v);
441 }
442 self
443 }
444 fn to_vec(self) -> Vec<T> {
445 match self {
446 Some(v) => vec![v],
447 None => vec![],
448 }
449 }
450 fn expect_msg(self, msg: &str) -> T {
451 match self {
452 Some(v) => v,
453 None => panic!("{msg}"),
454 }
455 }
456}
457pub fn option_chain_lookup<'a, K: PartialEq, V>(key: &K, maps: &[&'a [(K, V)]]) -> Option<&'a V> {
459 for map in maps {
460 if let Some(v) = map.iter().find(|(k, _)| k == key).map(|(_, v)| v) {
461 return Some(v);
462 }
463 }
464 None
465}
466pub fn option_first_of<T>(value: T, transforms: &[&dyn Fn(T) -> (T, Option<T>)]) -> Option<T>
468where
469 T: Clone,
470{
471 let mut current = value;
472 for transform in transforms {
473 let (next, result) = transform(current.clone());
474 if result.is_some() {
475 return result;
476 }
477 current = next;
478 }
479 None
480}
481pub fn best_option<T>(options: Vec<WeightedOption<T>>) -> Option<T> {
483 options
484 .into_iter()
485 .filter(|o| o.value.is_some())
486 .max_by(|a, b| {
487 a.weight
488 .partial_cmp(&b.weight)
489 .unwrap_or(std::cmp::Ordering::Equal)
490 })
491 .and_then(|o| o.value)
492}
493#[cfg(test)]
494mod extra_tests {
495 use super::*;
496 #[test]
497 fn test_option_ext_try_map() {
498 let r: Result<Option<u32>, &str> = Some(5u32).try_map(|x| Ok::<u32, &str>(x * 2));
499 assert_eq!(r, Ok(Some(10)));
500 let r2: Result<Option<u32>, &str> = None.try_map(|x: u32| Ok::<u32, &str>(x * 2));
501 assert_eq!(r2, Ok(None));
502 }
503 #[test]
504 fn test_option_ext_is_some_and() {
505 assert!(Some(5u32).is_some_and(|x| x > 3));
506 assert!(!Some(2u32).is_some_and(|x| x > 3));
507 assert!(!None::<u32>.is_some_and(|x| x > 3));
508 }
509 #[test]
510 fn test_option_ext_to_vec() {
511 assert_eq!(Some(42u32).to_vec(), vec![42]);
512 assert_eq!(None::<u32>.to_vec(), Vec::<u32>::new());
513 }
514 #[test]
515 fn test_option_ext_and_also() {
516 let r = Some(1u32).and_also(Some(2u32));
517 assert_eq!(r, Some((1, 2)));
518 let r2 = None::<u32>.and_also(Some(2));
519 assert!(r2.is_none());
520 }
521 #[test]
522 fn test_weighted_option() {
523 let opts = vec![
524 WeightedOption::some(0.8, "high"),
525 WeightedOption::some(0.5, "low"),
526 WeightedOption::none(0.9),
527 ];
528 let best = best_option(opts);
529 assert_eq!(best, Some("high"));
530 }
531 #[test]
532 fn test_option_cache() {
533 let mut cache: OptionCache<&str, u32> = OptionCache::new();
534 let v = cache.get_or_insert_with("a", || Some(42));
535 assert_eq!(v, Some(42));
536 let v2 = cache.get_or_insert_with("a", || Some(999));
537 assert_eq!(v2, Some(42));
538 assert_eq!(cache.len(), 1);
539 }
540 #[test]
541 fn test_option_cache_invalidate() {
542 let mut cache: OptionCache<&str, u32> = OptionCache::new();
543 cache.insert("x", Some(10));
544 cache.invalidate(&"x");
545 assert!(cache.is_empty());
546 }
547 #[test]
548 fn test_option_count_some() {
549 let opts = vec![Some(1u32), None, Some(3), None, Some(5)];
550 assert_eq!(option_count_some(opts), 3);
551 }
552 #[test]
553 fn test_option_annotate() {
554 let xs = vec![2u32, 3, 4];
555 let ann = option_annotate(&xs, |x| if x % 2 == 0 { Some(*x / 2) } else { None });
556 assert_eq!(ann[0].1, Some(1));
557 assert_eq!(ann[1].1, None);
558 assert_eq!(ann[2].1, Some(2));
559 }
560 #[test]
561 fn test_option_find() {
562 let v = vec![1u32, 2, 3, 4, 5];
563 let found = option_find(v, |x| *x > 3);
564 assert_eq!(found, Some(4));
565 }
566}
567#[allow(dead_code)]
569pub fn option_to_result<T>(opt: Option<T>, msg: &'static str) -> Result<T, &'static str> {
570 opt.ok_or(msg)
571}
572#[allow(dead_code)]
574pub fn result_ok<T, E>(r: Result<T, E>) -> Option<T> {
575 r.ok()
576}
577#[allow(dead_code)]
579pub fn option_both<T: Clone, U, V>(
580 opt: Option<T>,
581 f: impl FnOnce(T) -> Option<U>,
582 g: impl FnOnce(T) -> Option<V>,
583) -> Option<(U, V)> {
584 let v = opt?;
585 let u = f(v.clone())?;
586 let w = g(v)?;
587 Some((u, w))
588}
589#[allow(dead_code)]
591pub fn option_or_default<T: Default>(opt: Option<T>) -> Option<T> {
592 Some(opt.unwrap_or_default())
593}
594#[allow(dead_code)]
596pub fn option_unwrap_or_compute<T>(opt: Option<T>, f: impl FnOnce() -> T) -> T {
597 opt.unwrap_or_else(f)
598}
599#[allow(dead_code)]
601pub fn option_map_with<T, U, S>(
602 opt: Option<T>,
603 state: S,
604 f: impl FnOnce(S, T) -> (S, U),
605) -> (S, Option<U>) {
606 match opt {
607 Some(v) => {
608 let (s2, u) = f(state, v);
609 (s2, Some(u))
610 }
611 None => (state, None),
612 }
613}
614#[allow(dead_code)]
616pub fn option_from_bool<T>(cond: bool, value: T) -> Option<T> {
617 if cond {
618 Some(value)
619 } else {
620 None
621 }
622}
623#[allow(dead_code)]
625pub fn option_catch<T>(f: impl FnOnce() -> T + std::panic::UnwindSafe) -> Option<T> {
626 std::panic::catch_unwind(f).ok()
627}
628#[allow(dead_code)]
630pub fn option_zip3<A, B, C>(a: Option<A>, b: Option<B>, c: Option<C>) -> Option<(A, B, C)> {
631 match (a, b, c) {
632 (Some(x), Some(y), Some(z)) => Some((x, y, z)),
633 _ => None,
634 }
635}
636#[allow(dead_code)]
638pub fn option_swap<A, B>(opt: Option<(A, B)>) -> Option<(B, A)> {
639 opt.map(|(a, b)| (b, a))
640}
641#[allow(dead_code)]
643pub fn option_get_or_insert<T: Clone>(opt: &mut Option<T>, value: T) -> T {
644 if opt.is_none() {
645 *opt = Some(value.clone());
646 value
647 } else {
648 opt.clone().expect("opt is Some: checked by is_none guard")
649 }
650}
651#[allow(dead_code)]
655pub fn option_select_priority<T>(
656 candidates: Vec<(u32, Option<T>)>,
657 min_priority: u32,
658) -> Option<T> {
659 candidates
660 .into_iter()
661 .filter(|(p, o)| *p >= min_priority && o.is_some())
662 .max_by_key(|(p, _)| *p)
663 .and_then(|(_, o)| o)
664}
665#[cfg(test)]
666mod option_bridge_tests {
667 use super::*;
668 #[test]
669 fn test_option_to_result_some() {
670 let r = option_to_result(Some(5u32), "missing");
671 assert_eq!(r, Ok(5));
672 }
673 #[test]
674 fn test_option_to_result_none() {
675 let r = option_to_result(None::<u32>, "missing");
676 assert_eq!(r, Err("missing"));
677 }
678 #[test]
679 fn test_option_iter_some() {
680 let iter = OptionIter::new(Some(42u32));
681 let v: Vec<u32> = iter.collect();
682 assert_eq!(v, vec![42]);
683 }
684 #[test]
685 fn test_option_iter_none() {
686 let iter = OptionIter::<u32>::new(None);
687 let v: Vec<u32> = iter.collect();
688 assert!(v.is_empty());
689 }
690 #[test]
691 fn test_option_zip3() {
692 assert_eq!(
693 option_zip3(Some(1u32), Some(2u32), Some(3u32)),
694 Some((1, 2, 3))
695 );
696 assert!(option_zip3(Some(1u32), None::<u32>, Some(3u32)).is_none());
697 }
698 #[test]
699 fn test_option_swap() {
700 let swapped = option_swap(Some((1u32, "hello")));
701 assert_eq!(swapped, Some(("hello", 1)));
702 }
703 #[test]
704 fn test_option_from_bool() {
705 assert_eq!(option_from_bool(true, 42u32), Some(42));
706 assert_eq!(option_from_bool(false, 42u32), None);
707 }
708 #[test]
709 fn test_option_select_priority() {
710 let candidates = vec![(1, Some(10u32)), (3, Some(30)), (2, Some(20))];
711 let v = option_select_priority(candidates, 2);
712 assert_eq!(v, Some(30));
713 }
714 #[test]
715 fn test_option_select_priority_none_below_min() {
716 let candidates = vec![(1, Some(10u32))];
717 let v = option_select_priority(candidates, 2);
718 assert!(v.is_none());
719 }
720 #[test]
721 fn test_option_memo() {
722 let mut memo: OptionMemo<u32, String> = OptionMemo::new();
723 let v = memo.get_or_compute(5, |k| Some(k.to_string()));
724 assert_eq!(v, Some("5".to_string()));
725 let v2 = memo.get_or_compute(5, |_| panic!("should not be called"));
726 assert_eq!(v2, Some("5".to_string()));
727 assert_eq!(memo.len(), 1);
728 }
729 #[test]
730 fn test_option_memo_clear() {
731 let mut memo: OptionMemo<u32, u32> = OptionMemo::new();
732 memo.get_or_compute(1, |k| Some(*k));
733 memo.clear();
734 assert!(memo.is_empty());
735 }
736 #[test]
737 fn test_option_both() {
738 let r = option_both(
739 Some(5u32),
740 |x| if x > 3 { Some(x * 2) } else { None },
741 |x| Some(x + 1),
742 );
743 assert_eq!(r, Some((10, 6)));
744 let r2 = option_both(
745 Some(1u32),
746 |x| if x > 3 { Some(x * 2) } else { None },
747 |x| Some(x + 1),
748 );
749 assert!(r2.is_none());
750 }
751 #[test]
752 fn test_option_map_with() {
753 let (state, result) = option_map_with(Some(5u32), 0u32, |s, v| (s + v, v * 2));
754 assert_eq!(state, 5);
755 assert_eq!(result, Some(10));
756 let (s2, r2) = option_map_with(None::<u32>, 0u32, |s, v| (s + v, v * 2));
757 assert_eq!(s2, 0);
758 assert!(r2.is_none());
759 }
760}
761pub(super) fn opt_ext_type0() -> Expr {
762 Expr::Sort(Level::succ(Level::zero()))
763}
764pub(super) fn opt_ext_prop() -> Expr {
765 Expr::Sort(Level::zero())
766}
767pub fn opt_ext_cst(name: &str) -> Expr {
768 Expr::Const(Name::str(name), vec![])
769}
770pub fn opt_ext_app(f: Expr, a: Expr) -> Expr {
771 Expr::App(Box::new(f), Box::new(a))
772}
773pub fn opt_ext_app2(f: Expr, a: Expr, b: Expr) -> Expr {
774 opt_ext_app(opt_ext_app(f, a), b)
775}
776pub fn opt_ext_app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
777 opt_ext_app(opt_ext_app2(f, a, b), c)
778}
779pub(super) fn opt_ext_pi(name: &str, dom: Expr, body: Expr) -> Expr {
780 Expr::Pi(
781 BinderInfo::Default,
782 Name::str(name),
783 Box::new(dom),
784 Box::new(body),
785 )
786}
787pub(super) fn opt_ext_pi_imp(name: &str, dom: Expr, body: Expr) -> Expr {
788 Expr::Pi(
789 BinderInfo::Implicit,
790 Name::str(name),
791 Box::new(dom),
792 Box::new(body),
793 )
794}
795pub(super) fn opt_ext_arrow(a: Expr, b: Expr) -> Expr {
796 opt_ext_pi("_", a, b)
797}
798pub(super) fn opt_ext_option_ty(alpha: Expr) -> Expr {
799 opt_ext_app(opt_ext_cst("Option"), alpha)
800}
801pub(super) fn opt_ext_axiom(env: &mut Environment, name: &str, ty: Expr) -> Result<(), String> {
802 env.add(Declaration::Axiom {
803 name: Name::str(name),
804 univ_params: vec![],
805 ty,
806 })
807 .map_err(|e| e.to_string())
808}
809pub fn opt_ext_monad_left_id(env: &mut Environment) -> Result<(), String> {
811 let t = opt_ext_type0();
812 let ty = opt_ext_pi_imp(
813 "α",
814 t.clone(),
815 opt_ext_pi_imp(
816 "β",
817 t.clone(),
818 opt_ext_pi(
819 "a",
820 Expr::BVar(1),
821 opt_ext_pi(
822 "f",
823 opt_ext_arrow(Expr::BVar(1), opt_ext_option_ty(Expr::BVar(1))),
824 opt_ext_prop(),
825 ),
826 ),
827 ),
828 );
829 opt_ext_axiom(env, "Option.monad_left_id", ty)
830}
831pub fn opt_ext_monad_right_id(env: &mut Environment) -> Result<(), String> {
833 let t = opt_ext_type0();
834 let opt_a = opt_ext_option_ty(Expr::BVar(0));
835 let ty = opt_ext_pi_imp(
836 "α",
837 t.clone(),
838 opt_ext_pi("m", opt_a.clone(), opt_ext_prop()),
839 );
840 opt_ext_axiom(env, "Option.monad_right_id", ty)
841}
842pub fn opt_ext_monad_assoc(env: &mut Environment) -> Result<(), String> {
844 let t = opt_ext_type0();
845 let ty = opt_ext_pi_imp(
846 "α",
847 t.clone(),
848 opt_ext_pi_imp(
849 "β",
850 t.clone(),
851 opt_ext_pi_imp(
852 "γ",
853 t.clone(),
854 opt_ext_pi(
855 "m",
856 opt_ext_option_ty(Expr::BVar(2)),
857 opt_ext_pi(
858 "f",
859 opt_ext_arrow(Expr::BVar(2), opt_ext_option_ty(Expr::BVar(2))),
860 opt_ext_pi(
861 "g",
862 opt_ext_arrow(Expr::BVar(2), opt_ext_option_ty(Expr::BVar(2))),
863 opt_ext_prop(),
864 ),
865 ),
866 ),
867 ),
868 ),
869 );
870 opt_ext_axiom(env, "Option.monad_assoc", ty)
871}
872pub fn opt_ext_functor_id(env: &mut Environment) -> Result<(), String> {
874 let t = opt_ext_type0();
875 let ty = opt_ext_pi_imp(
876 "α",
877 t.clone(),
878 opt_ext_pi("m", opt_ext_option_ty(Expr::BVar(0)), opt_ext_prop()),
879 );
880 opt_ext_axiom(env, "Option.functor_id", ty)
881}
882pub fn opt_ext_functor_comp(env: &mut Environment) -> Result<(), String> {
884 let t = opt_ext_type0();
885 let ty = opt_ext_pi_imp(
886 "α",
887 t.clone(),
888 opt_ext_pi_imp(
889 "β",
890 t.clone(),
891 opt_ext_pi_imp(
892 "γ",
893 t.clone(),
894 opt_ext_pi(
895 "f",
896 opt_ext_arrow(Expr::BVar(1), Expr::BVar(1)),
897 opt_ext_pi(
898 "g",
899 opt_ext_arrow(Expr::BVar(3), Expr::BVar(3)),
900 opt_ext_prop(),
901 ),
902 ),
903 ),
904 ),
905 );
906 opt_ext_axiom(env, "Option.functor_comp", ty)
907}
908pub fn opt_ext_ap_identity(env: &mut Environment) -> Result<(), String> {
910 let t = opt_ext_type0();
911 let ty = opt_ext_pi_imp(
912 "α",
913 t.clone(),
914 opt_ext_pi("v", opt_ext_option_ty(Expr::BVar(0)), opt_ext_prop()),
915 );
916 opt_ext_axiom(env, "Option.ap_identity", ty)
917}
918pub fn opt_ext_ap_homomorphism(env: &mut Environment) -> Result<(), String> {
920 let t = opt_ext_type0();
921 let ty = opt_ext_pi_imp(
922 "α",
923 t.clone(),
924 opt_ext_pi_imp(
925 "β",
926 t.clone(),
927 opt_ext_pi(
928 "f",
929 opt_ext_arrow(Expr::BVar(1), Expr::BVar(1)),
930 opt_ext_pi("x", Expr::BVar(2), opt_ext_prop()),
931 ),
932 ),
933 );
934 opt_ext_axiom(env, "Option.ap_homomorphism", ty)
935}
936pub fn opt_ext_ap_interchange(env: &mut Environment) -> Result<(), String> {
938 let t = opt_ext_type0();
939 let ty = opt_ext_pi_imp(
940 "α",
941 t.clone(),
942 opt_ext_pi_imp(
943 "β",
944 t.clone(),
945 opt_ext_pi(
946 "u",
947 opt_ext_option_ty(opt_ext_arrow(Expr::BVar(1), Expr::BVar(1))),
948 opt_ext_pi("y", Expr::BVar(2), opt_ext_prop()),
949 ),
950 ),
951 );
952 opt_ext_axiom(env, "Option.ap_interchange", ty)
953}
954pub fn opt_ext_ap_composition(env: &mut Environment) -> Result<(), String> {
956 let t = opt_ext_type0();
957 let ty = opt_ext_pi_imp(
958 "α",
959 t.clone(),
960 opt_ext_pi_imp(
961 "β",
962 t.clone(),
963 opt_ext_pi_imp("γ", t.clone(), opt_ext_prop()),
964 ),
965 );
966 opt_ext_axiom(env, "Option.ap_composition", ty)
967}
968pub fn opt_ext_alt_first_some(env: &mut Environment) -> Result<(), String> {
970 let t = opt_ext_type0();
971 let ty = opt_ext_pi_imp(
972 "α",
973 t.clone(),
974 opt_ext_pi(
975 "x",
976 Expr::BVar(0),
977 opt_ext_pi("other", opt_ext_option_ty(Expr::BVar(1)), opt_ext_prop()),
978 ),
979 );
980 opt_ext_axiom(env, "Option.alt_first_some", ty)
981}
982pub fn opt_ext_alt_none_left(env: &mut Environment) -> Result<(), String> {
984 let t = opt_ext_type0();
985 let ty = opt_ext_pi_imp(
986 "α",
987 t.clone(),
988 opt_ext_pi("m", opt_ext_option_ty(Expr::BVar(0)), opt_ext_prop()),
989 );
990 opt_ext_axiom(env, "Option.alt_none_left", ty)
991}
992pub fn opt_ext_alt_assoc(env: &mut Environment) -> Result<(), String> {
994 let t = opt_ext_type0();
995 let oa = opt_ext_option_ty(Expr::BVar(0));
996 let ty = opt_ext_pi_imp(
997 "α",
998 t.clone(),
999 opt_ext_pi(
1000 "a",
1001 oa.clone(),
1002 opt_ext_pi("b", oa.clone(), opt_ext_pi("c", oa.clone(), opt_ext_prop())),
1003 ),
1004 );
1005 opt_ext_axiom(env, "Option.alt_assoc", ty)
1006}
1007pub fn opt_ext_iso_to_either(env: &mut Environment) -> Result<(), String> {
1009 let t = opt_ext_type0();
1010 let opt_a = opt_ext_option_ty(Expr::BVar(0));
1011 let either_unit_a = opt_ext_app2(opt_ext_cst("Either"), opt_ext_cst("Unit"), Expr::BVar(0));
1012 let ty = opt_ext_pi_imp("α", t.clone(), opt_ext_arrow(opt_a, either_unit_a));
1013 opt_ext_axiom(env, "Option.iso_to_either", ty)
1014}
1015pub fn opt_ext_iso_from_either(env: &mut Environment) -> Result<(), String> {
1017 let t = opt_ext_type0();
1018 let opt_a = opt_ext_option_ty(Expr::BVar(0));
1019 let either_unit_a = opt_ext_app2(opt_ext_cst("Either"), opt_ext_cst("Unit"), Expr::BVar(0));
1020 let ty = opt_ext_pi_imp("α", t.clone(), opt_ext_arrow(either_unit_a, opt_a));
1021 opt_ext_axiom(env, "Option.iso_from_either", ty)
1022}
1023pub fn opt_ext_iso_roundtrip_to(env: &mut Environment) -> Result<(), String> {
1025 let t = opt_ext_type0();
1026 let ty = opt_ext_pi_imp(
1027 "α",
1028 t.clone(),
1029 opt_ext_pi("x", opt_ext_option_ty(Expr::BVar(0)), opt_ext_prop()),
1030 );
1031 opt_ext_axiom(env, "Option.iso_roundtrip_to", ty)
1032}
1033pub fn opt_ext_iso_roundtrip_from(env: &mut Environment) -> Result<(), String> {
1035 let t = opt_ext_type0();
1036 let either_unit_a = opt_ext_app2(opt_ext_cst("Either"), opt_ext_cst("Unit"), Expr::BVar(0));
1037 let ty = opt_ext_pi_imp(
1038 "α",
1039 t.clone(),
1040 opt_ext_pi("y", either_unit_a, opt_ext_prop()),
1041 );
1042 opt_ext_axiom(env, "Option.iso_roundtrip_from", ty)
1043}
1044pub fn opt_ext_cata(env: &mut Environment) -> Result<(), String> {
1046 let t = opt_ext_type0();
1047 let ty = opt_ext_pi_imp(
1048 "α",
1049 t.clone(),
1050 opt_ext_pi_imp(
1051 "β",
1052 t.clone(),
1053 opt_ext_pi(
1054 "n",
1055 Expr::BVar(0),
1056 opt_ext_pi(
1057 "s",
1058 opt_ext_arrow(Expr::BVar(2), Expr::BVar(1)),
1059 opt_ext_arrow(opt_ext_option_ty(Expr::BVar(3)), Expr::BVar(2)),
1060 ),
1061 ),
1062 ),
1063 );
1064 opt_ext_axiom(env, "Option.cata", ty)
1065}
1066pub fn opt_ext_ana(env: &mut Environment) -> Result<(), String> {
1068 let t = opt_ext_type0();
1069 let ty = opt_ext_pi_imp(
1070 "α",
1071 t.clone(),
1072 opt_ext_pi_imp(
1073 "β",
1074 t.clone(),
1075 opt_ext_pi(
1076 "coalg",
1077 opt_ext_arrow(Expr::BVar(0), opt_ext_option_ty(Expr::BVar(1))),
1078 opt_ext_arrow(Expr::BVar(1), opt_ext_option_ty(Expr::BVar(2))),
1079 ),
1080 ),
1081 );
1082 opt_ext_axiom(env, "Option.ana", ty)
1083}
1084pub fn opt_ext_traverse_id(env: &mut Environment) -> Result<(), String> {
1086 let t = opt_ext_type0();
1087 let ty = opt_ext_pi_imp(
1088 "α",
1089 t.clone(),
1090 opt_ext_pi("m", opt_ext_option_ty(Expr::BVar(0)), opt_ext_prop()),
1091 );
1092 opt_ext_axiom(env, "Option.traverse_id", ty)
1093}
1094pub fn opt_ext_traverse_comp(env: &mut Environment) -> Result<(), String> {
1096 let t = opt_ext_type0();
1097 let ty = opt_ext_pi_imp(
1098 "α",
1099 t.clone(),
1100 opt_ext_pi_imp(
1101 "β",
1102 t.clone(),
1103 opt_ext_pi_imp("γ", t.clone(), opt_ext_prop()),
1104 ),
1105 );
1106 opt_ext_axiom(env, "Option.traverse_comp", ty)
1107}
1108pub fn opt_ext_sequence_traverse(env: &mut Environment) -> Result<(), String> {
1110 let t = opt_ext_type0();
1111 let ty = opt_ext_pi_imp("α", t.clone(), opt_ext_prop());
1112 opt_ext_axiom(env, "Option.sequence_traverse", ty)
1113}
1114pub fn opt_ext_foldable_foldl(env: &mut Environment) -> Result<(), String> {
1116 let t = opt_ext_type0();
1117 let ty = opt_ext_pi_imp(
1118 "α",
1119 t.clone(),
1120 opt_ext_pi_imp(
1121 "β",
1122 t.clone(),
1123 opt_ext_pi(
1124 "f",
1125 opt_ext_arrow(Expr::BVar(0), opt_ext_arrow(Expr::BVar(1), Expr::BVar(1))),
1126 opt_ext_pi(
1127 "z",
1128 Expr::BVar(1),
1129 opt_ext_pi("x", Expr::BVar(3), opt_ext_prop()),
1130 ),
1131 ),
1132 ),
1133 );
1134 opt_ext_axiom(env, "Option.foldable_foldl", ty)
1135}
1136pub fn opt_ext_foldable_foldr(env: &mut Environment) -> Result<(), String> {
1138 let t = opt_ext_type0();
1139 let ty = opt_ext_pi_imp(
1140 "α",
1141 t.clone(),
1142 opt_ext_pi_imp(
1143 "β",
1144 t.clone(),
1145 opt_ext_pi(
1146 "f",
1147 opt_ext_arrow(Expr::BVar(1), opt_ext_arrow(Expr::BVar(1), Expr::BVar(1))),
1148 opt_ext_pi(
1149 "z",
1150 Expr::BVar(1),
1151 opt_ext_pi("x", Expr::BVar(3), opt_ext_prop()),
1152 ),
1153 ),
1154 ),
1155 );
1156 opt_ext_axiom(env, "Option.foldable_foldr", ty)
1157}
1158pub fn opt_ext_foldable_fold_none(env: &mut Environment) -> Result<(), String> {
1160 let t = opt_ext_type0();
1161 let ty = opt_ext_pi_imp(
1162 "α",
1163 t.clone(),
1164 opt_ext_pi_imp(
1165 "β",
1166 t.clone(),
1167 opt_ext_pi(
1168 "f",
1169 opt_ext_arrow(Expr::BVar(0), opt_ext_arrow(Expr::BVar(1), Expr::BVar(1))),
1170 opt_ext_pi("z", Expr::BVar(1), opt_ext_prop()),
1171 ),
1172 ),
1173 );
1174 opt_ext_axiom(env, "Option.foldable_fold_none", ty)
1175}
1176pub fn opt_ext_optiont_run(env: &mut Environment) -> Result<(), String> {
1178 let t = opt_ext_type0();
1179 let ty = opt_ext_pi_imp(
1180 "m",
1181 opt_ext_arrow(t.clone(), t.clone()),
1182 opt_ext_pi_imp(
1183 "α",
1184 t.clone(),
1185 opt_ext_arrow(
1186 opt_ext_app(Expr::BVar(1), opt_ext_option_ty(Expr::BVar(0))),
1187 opt_ext_app(Expr::BVar(1), opt_ext_option_ty(Expr::BVar(0))),
1188 ),
1189 ),
1190 );
1191 opt_ext_axiom(env, "OptionT.run", ty)
1192}
1193pub fn opt_ext_optiont_lift(env: &mut Environment) -> Result<(), String> {
1195 let t = opt_ext_type0();
1196 let ty = opt_ext_pi_imp(
1197 "m",
1198 opt_ext_arrow(t.clone(), t.clone()),
1199 opt_ext_pi_imp(
1200 "α",
1201 t.clone(),
1202 opt_ext_arrow(
1203 opt_ext_app(Expr::BVar(1), Expr::BVar(0)),
1204 opt_ext_app(Expr::BVar(1), opt_ext_option_ty(Expr::BVar(0))),
1205 ),
1206 ),
1207 );
1208 opt_ext_axiom(env, "OptionT.lift", ty)
1209}
1210pub fn opt_ext_optiont_bind(env: &mut Environment) -> Result<(), String> {
1212 let t = opt_ext_type0();
1213 let ty = opt_ext_pi_imp(
1214 "m",
1215 opt_ext_arrow(t.clone(), t.clone()),
1216 opt_ext_pi_imp(
1217 "α",
1218 t.clone(),
1219 opt_ext_pi_imp("β", t.clone(), opt_ext_prop()),
1220 ),
1221 );
1222 opt_ext_axiom(env, "OptionT.bind", ty)
1223}
1224pub fn opt_ext_pointed_pure(env: &mut Environment) -> Result<(), String> {
1226 let t = opt_ext_type0();
1227 let ty = opt_ext_pi_imp(
1228 "α",
1229 t.clone(),
1230 opt_ext_pi("x", Expr::BVar(0), opt_ext_prop()),
1231 );
1232 opt_ext_axiom(env, "Option.pointed_pure", ty)
1233}
1234pub fn opt_ext_monoid_empty(env: &mut Environment) -> Result<(), String> {
1236 let t = opt_ext_type0();
1237 let ty = opt_ext_pi_imp("α", t.clone(), opt_ext_option_ty(Expr::BVar(0)));
1238 opt_ext_axiom(env, "Option.monoid_empty", ty)
1239}
1240pub fn opt_ext_monoid_append(env: &mut Environment) -> Result<(), String> {
1242 let t = opt_ext_type0();
1243 let oa = opt_ext_option_ty(Expr::BVar(0));
1244 let ty = opt_ext_pi_imp(
1245 "α",
1246 t.clone(),
1247 opt_ext_arrow(oa.clone(), opt_ext_arrow(oa.clone(), oa.clone())),
1248 );
1249 opt_ext_axiom(env, "Option.monoid_append", ty)
1250}
1251pub fn opt_ext_monoid_left_id(env: &mut Environment) -> Result<(), String> {
1253 let t = opt_ext_type0();
1254 let ty = opt_ext_pi_imp(
1255 "α",
1256 t.clone(),
1257 opt_ext_pi("m", opt_ext_option_ty(Expr::BVar(0)), opt_ext_prop()),
1258 );
1259 opt_ext_axiom(env, "Option.monoid_left_id", ty)
1260}
1261pub fn opt_ext_monoid_right_id(env: &mut Environment) -> Result<(), String> {
1263 let t = opt_ext_type0();
1264 let ty = opt_ext_pi_imp(
1265 "α",
1266 t.clone(),
1267 opt_ext_pi("m", opt_ext_option_ty(Expr::BVar(0)), opt_ext_prop()),
1268 );
1269 opt_ext_axiom(env, "Option.monoid_right_id", ty)
1270}
1271pub fn opt_ext_bimap_some(env: &mut Environment) -> Result<(), String> {
1273 let t = opt_ext_type0();
1274 let ty = opt_ext_pi_imp(
1275 "α",
1276 t.clone(),
1277 opt_ext_pi_imp(
1278 "β",
1279 t.clone(),
1280 opt_ext_pi(
1281 "f",
1282 opt_ext_arrow(Expr::BVar(1), Expr::BVar(1)),
1283 opt_ext_pi("x", Expr::BVar(2), opt_ext_prop()),
1284 ),
1285 ),
1286 );
1287 opt_ext_axiom(env, "Option.bimap_some", ty)
1288}
1289pub fn opt_ext_bimap_none(env: &mut Environment) -> Result<(), String> {
1291 let t = opt_ext_type0();
1292 let ty = opt_ext_pi_imp(
1293 "α",
1294 t.clone(),
1295 opt_ext_pi_imp(
1296 "β",
1297 t.clone(),
1298 opt_ext_pi(
1299 "f",
1300 opt_ext_arrow(Expr::BVar(1), Expr::BVar(1)),
1301 opt_ext_prop(),
1302 ),
1303 ),
1304 );
1305 opt_ext_axiom(env, "Option.bimap_none", ty)
1306}
1307pub fn opt_ext_zip_some(env: &mut Environment) -> Result<(), String> {
1309 let t = opt_ext_type0();
1310 let ty = opt_ext_pi_imp(
1311 "α",
1312 t.clone(),
1313 opt_ext_pi_imp(
1314 "β",
1315 t.clone(),
1316 opt_ext_pi(
1317 "a",
1318 Expr::BVar(1),
1319 opt_ext_pi("b", Expr::BVar(1), opt_ext_prop()),
1320 ),
1321 ),
1322 );
1323 opt_ext_axiom(env, "Option.zip_some", ty)
1324}
1325pub fn opt_ext_zip_none(env: &mut Environment) -> Result<(), String> {
1327 let t = opt_ext_type0();
1328 let ty = opt_ext_pi_imp(
1329 "α",
1330 t.clone(),
1331 opt_ext_pi_imp(
1332 "β",
1333 t.clone(),
1334 opt_ext_pi("b", opt_ext_option_ty(Expr::BVar(0)), opt_ext_prop()),
1335 ),
1336 );
1337 opt_ext_axiom(env, "Option.zip_none", ty)
1338}
1339pub fn opt_ext_filter_some_true(env: &mut Environment) -> Result<(), String> {
1341 let t = opt_ext_type0();
1342 let ty = opt_ext_pi_imp(
1343 "α",
1344 t.clone(),
1345 opt_ext_pi(
1346 "p",
1347 opt_ext_arrow(Expr::BVar(0), opt_ext_cst("Bool")),
1348 opt_ext_pi("x", Expr::BVar(1), opt_ext_prop()),
1349 ),
1350 );
1351 opt_ext_axiom(env, "Option.filter_some_true", ty)
1352}
1353pub fn opt_ext_filter_some_false(env: &mut Environment) -> Result<(), String> {
1355 let t = opt_ext_type0();
1356 let ty = opt_ext_pi_imp(
1357 "α",
1358 t.clone(),
1359 opt_ext_pi(
1360 "p",
1361 opt_ext_arrow(Expr::BVar(0), opt_ext_cst("Bool")),
1362 opt_ext_pi("x", Expr::BVar(1), opt_ext_prop()),
1363 ),
1364 );
1365 opt_ext_axiom(env, "Option.filter_some_false", ty)
1366}
1367pub fn opt_ext_filter_none(env: &mut Environment) -> Result<(), String> {
1369 let t = opt_ext_type0();
1370 let ty = opt_ext_pi_imp(
1371 "α",
1372 t.clone(),
1373 opt_ext_pi(
1374 "p",
1375 opt_ext_arrow(Expr::BVar(0), opt_ext_cst("Bool")),
1376 opt_ext_prop(),
1377 ),
1378 );
1379 opt_ext_axiom(env, "Option.filter_none", ty)
1380}
1381pub fn opt_ext_get_or_else_some(env: &mut Environment) -> Result<(), String> {
1383 let t = opt_ext_type0();
1384 let ty = opt_ext_pi_imp(
1385 "α",
1386 t.clone(),
1387 opt_ext_pi(
1388 "x",
1389 Expr::BVar(0),
1390 opt_ext_pi("d", Expr::BVar(1), opt_ext_prop()),
1391 ),
1392 );
1393 opt_ext_axiom(env, "Option.get_or_else_some", ty)
1394}
1395pub fn opt_ext_get_or_else_none(env: &mut Environment) -> Result<(), String> {
1397 let t = opt_ext_type0();
1398 let ty = opt_ext_pi_imp(
1399 "α",
1400 t.clone(),
1401 opt_ext_pi("d", Expr::BVar(0), opt_ext_prop()),
1402 );
1403 opt_ext_axiom(env, "Option.get_or_else_none", ty)
1404}
1405pub fn opt_ext_or_else_some(env: &mut Environment) -> Result<(), String> {
1407 let t = opt_ext_type0();
1408 let oa = opt_ext_option_ty(Expr::BVar(0));
1409 let ty = opt_ext_pi_imp(
1410 "α",
1411 t.clone(),
1412 opt_ext_pi(
1413 "x",
1414 Expr::BVar(0),
1415 opt_ext_pi("other", oa.clone(), opt_ext_prop()),
1416 ),
1417 );
1418 opt_ext_axiom(env, "Option.or_else_some", ty)
1419}
1420pub fn opt_ext_or_else_none(env: &mut Environment) -> Result<(), String> {
1422 let t = opt_ext_type0();
1423 let ty = opt_ext_pi_imp(
1424 "α",
1425 t.clone(),
1426 opt_ext_pi("m", opt_ext_option_ty(Expr::BVar(0)), opt_ext_prop()),
1427 );
1428 opt_ext_axiom(env, "Option.or_else_none", ty)
1429}
1430pub fn opt_ext_dimap(env: &mut Environment) -> Result<(), String> {
1432 let t = opt_ext_type0();
1433 let ty = opt_ext_pi_imp(
1434 "α",
1435 t.clone(),
1436 opt_ext_pi_imp(
1437 "β",
1438 t.clone(),
1439 opt_ext_pi_imp(
1440 "γ",
1441 t.clone(),
1442 opt_ext_pi_imp(
1443 "δ",
1444 t.clone(),
1445 opt_ext_pi(
1446 "pre",
1447 opt_ext_arrow(Expr::BVar(2), Expr::BVar(3)),
1448 opt_ext_pi(
1449 "post",
1450 opt_ext_arrow(Expr::BVar(2), Expr::BVar(2)),
1451 opt_ext_pi(
1452 "f",
1453 opt_ext_arrow(Expr::BVar(5), opt_ext_option_ty(Expr::BVar(3))),
1454 opt_ext_arrow(Expr::BVar(5), opt_ext_option_ty(Expr::BVar(4))),
1455 ),
1456 ),
1457 ),
1458 ),
1459 ),
1460 ),
1461 );
1462 opt_ext_axiom(env, "Option.dimap", ty)
1463}
1464pub fn opt_ext_comonad_extract(env: &mut Environment) -> Result<(), String> {
1466 let t = opt_ext_type0();
1467 let ty = opt_ext_pi_imp(
1468 "α",
1469 t.clone(),
1470 opt_ext_pi(
1471 "m",
1472 opt_ext_option_ty(Expr::BVar(0)),
1473 opt_ext_pi("d", Expr::BVar(1), opt_ext_prop()),
1474 ),
1475 );
1476 opt_ext_axiom(env, "Option.comonad_extract", ty)
1477}
1478pub fn opt_ext_join_some_some(env: &mut Environment) -> Result<(), String> {
1480 let t = opt_ext_type0();
1481 let inner = opt_ext_option_ty(Expr::BVar(0));
1482 let outer = opt_ext_option_ty(inner);
1483 let ty = opt_ext_pi_imp(
1484 "α",
1485 t.clone(),
1486 opt_ext_pi("x", Expr::BVar(0), opt_ext_pi("m", outer, opt_ext_prop())),
1487 );
1488 opt_ext_axiom(env, "Option.join_some_some", ty)
1489}
1490pub fn opt_ext_join_some_none(env: &mut Environment) -> Result<(), String> {
1492 let t = opt_ext_type0();
1493 let ty = opt_ext_pi_imp("α", t.clone(), opt_ext_prop());
1494 opt_ext_axiom(env, "Option.join_some_none", ty)
1495}
1496pub fn opt_ext_join_none(env: &mut Environment) -> Result<(), String> {
1498 let t = opt_ext_type0();
1499 let ty = opt_ext_pi_imp("α", t.clone(), opt_ext_prop());
1500 opt_ext_axiom(env, "Option.join_none", ty)
1501}
1502pub fn opt_ext_flatmap_is_join_map(env: &mut Environment) -> Result<(), String> {
1504 let t = opt_ext_type0();
1505 let ty = opt_ext_pi_imp(
1506 "α",
1507 t.clone(),
1508 opt_ext_pi_imp(
1509 "β",
1510 t.clone(),
1511 opt_ext_pi(
1512 "m",
1513 opt_ext_option_ty(Expr::BVar(1)),
1514 opt_ext_pi(
1515 "f",
1516 opt_ext_arrow(Expr::BVar(2), opt_ext_option_ty(Expr::BVar(2))),
1517 opt_ext_prop(),
1518 ),
1519 ),
1520 ),
1521 );
1522 opt_ext_axiom(env, "Option.flatmap_is_join_map", ty)
1523}
1524pub fn opt_ext_nullable_iso_to(env: &mut Environment) -> Result<(), String> {
1526 let t = opt_ext_type0();
1527 let ty = opt_ext_pi_imp(
1528 "α",
1529 t.clone(),
1530 opt_ext_arrow(
1531 opt_ext_option_ty(Expr::BVar(0)),
1532 opt_ext_option_ty(Expr::BVar(0)),
1533 ),
1534 );
1535 opt_ext_axiom(env, "Option.nullable_iso_to", ty)
1536}
1537pub fn opt_ext_nullable_iso_from(env: &mut Environment) -> Result<(), String> {
1539 let t = opt_ext_type0();
1540 let ty = opt_ext_pi_imp(
1541 "α",
1542 t.clone(),
1543 opt_ext_arrow(
1544 opt_ext_option_ty(Expr::BVar(0)),
1545 opt_ext_option_ty(Expr::BVar(0)),
1546 ),
1547 );
1548 opt_ext_axiom(env, "Option.nullable_iso_from", ty)
1549}
1550pub fn opt_ext_lift_a2(env: &mut Environment) -> Result<(), String> {
1552 let t = opt_ext_type0();
1553 let ty = opt_ext_pi_imp(
1554 "α",
1555 t.clone(),
1556 opt_ext_pi_imp(
1557 "β",
1558 t.clone(),
1559 opt_ext_pi_imp(
1560 "γ",
1561 t.clone(),
1562 opt_ext_pi(
1563 "f",
1564 opt_ext_arrow(Expr::BVar(2), opt_ext_arrow(Expr::BVar(2), Expr::BVar(2))),
1565 opt_ext_pi(
1566 "u",
1567 opt_ext_option_ty(Expr::BVar(3)),
1568 opt_ext_pi("v", opt_ext_option_ty(Expr::BVar(3)), opt_ext_prop()),
1569 ),
1570 ),
1571 ),
1572 ),
1573 );
1574 opt_ext_axiom(env, "Option.liftA2_def", ty)
1575}
1576pub fn register_option_extended_axioms(env: &mut Environment) -> Result<(), String> {
1584 let t = opt_ext_type0();
1585 for name in ["Bool", "Option", "Either", "Unit", "Nat", "List", "Prod"] {
1586 let _ = env.add(Declaration::Axiom {
1587 name: Name::str(name),
1588 univ_params: vec![],
1589 ty: t.clone(),
1590 });
1591 }
1592 opt_ext_monad_left_id(env)?;
1593 opt_ext_monad_right_id(env)?;
1594 opt_ext_monad_assoc(env)?;
1595 opt_ext_functor_id(env)?;
1596 opt_ext_functor_comp(env)?;
1597 opt_ext_ap_identity(env)?;
1598 opt_ext_ap_homomorphism(env)?;
1599 opt_ext_ap_interchange(env)?;
1600 opt_ext_ap_composition(env)?;
1601 opt_ext_alt_first_some(env)?;
1602 opt_ext_alt_none_left(env)?;
1603 opt_ext_alt_assoc(env)?;
1604 opt_ext_iso_to_either(env)?;
1605 opt_ext_iso_from_either(env)?;
1606 opt_ext_iso_roundtrip_to(env)?;
1607 opt_ext_iso_roundtrip_from(env)?;
1608 opt_ext_cata(env)?;
1609 opt_ext_ana(env)?;
1610 opt_ext_traverse_id(env)?;
1611 opt_ext_traverse_comp(env)?;
1612 opt_ext_sequence_traverse(env)?;
1613 opt_ext_foldable_foldl(env)?;
1614 opt_ext_foldable_foldr(env)?;
1615 opt_ext_foldable_fold_none(env)?;
1616 opt_ext_optiont_run(env)?;
1617 opt_ext_optiont_lift(env)?;
1618 opt_ext_optiont_bind(env)?;
1619 opt_ext_pointed_pure(env)?;
1620 opt_ext_monoid_empty(env)?;
1621 opt_ext_monoid_append(env)?;
1622 opt_ext_monoid_left_id(env)?;
1623 opt_ext_monoid_right_id(env)?;
1624 opt_ext_bimap_some(env)?;
1625 opt_ext_bimap_none(env)?;
1626 opt_ext_zip_some(env)?;
1627 opt_ext_zip_none(env)?;
1628 opt_ext_filter_some_true(env)?;
1629 opt_ext_filter_some_false(env)?;
1630 opt_ext_filter_none(env)?;
1631 opt_ext_get_or_else_some(env)?;
1632 opt_ext_get_or_else_none(env)?;
1633 opt_ext_or_else_some(env)?;
1634 opt_ext_or_else_none(env)?;
1635 opt_ext_dimap(env)?;
1636 opt_ext_comonad_extract(env)?;
1637 opt_ext_join_some_some(env)?;
1638 opt_ext_join_some_none(env)?;
1639 opt_ext_join_none(env)?;
1640 opt_ext_flatmap_is_join_map(env)?;
1641 opt_ext_nullable_iso_to(env)?;
1642 opt_ext_nullable_iso_from(env)?;
1643 opt_ext_lift_a2(env)?;
1644 Ok(())
1645}