1use super::{unify_entries, LMap};
2use canrun::{custom, project_2, DomainType, Goal, IntoVal, UnifyIn};
3use std::fmt::Debug;
4use std::hash::Hash;
5
6pub fn is_subset<'a, K, V, A, B, D>(a: A, b: B) -> Goal<'a, D>
23where
24 K: Debug + Eq + Hash + UnifyIn<'a, D> + 'a,
25 V: Debug + UnifyIn<'a, D> + 'a,
26 A: IntoVal<LMap<K, V>>,
27 B: IntoVal<LMap<K, V>>,
28 D: DomainType<'a, LMap<K, V>> + DomainType<'a, K> + DomainType<'a, V> + 'a,
29{
30 project_2(a, b, |a, b| {
31 custom(move |state| unify_entries(state, a.clone(), b.clone()))
32 })
33}
34
35pub fn is_superset<'a, K, V, A, B, D>(a: A, b: B) -> Goal<'a, D>
52where
53 K: Debug + Eq + Hash + UnifyIn<'a, D> + 'a,
54 V: Debug + UnifyIn<'a, D> + 'a,
55 A: IntoVal<LMap<K, V>>,
56 B: IntoVal<LMap<K, V>>,
57 D: DomainType<'a, LMap<K, V>> + DomainType<'a, K> + DomainType<'a, V> + 'a,
58{
59 is_subset(b, a)
60}
61
62#[cfg(test)]
63mod tests {
64 use super::{is_subset, is_superset};
65 use crate::example::Collections;
66 use crate::lmap;
67 use canrun::{var, Goal, IterResolved};
68
69 #[test]
70 fn is_subset_should_succeed_on() {
71 let x = var();
72 let cases = vec![
73 (lmap! {1 => 2}, lmap! {1 => 2}),
74 (lmap! {1 => 2}, lmap! {1 => 2, 3 => 4}),
75 (lmap! {x => 2}, lmap! {1 => 2, 3 => 4}),
76 (lmap! {x => 2}, lmap! {x => 2, 3 => 4}),
77 ];
78 for (a, b) in cases {
79 let goal: Goal<Collections> = is_subset(&a, &b);
80 if goal.iter_resolved().count() != 1 {
81 panic!("is_subset failed on {:?} {:?}", a, b);
82 }
83 }
84 }
85
86 #[test]
87 fn is_subset_should_fail_on() {
88 let x = var();
89 let cases = vec![
90 (lmap! {1 => 2, 3 => 4}, lmap! {1 => 2}),
91 (lmap! {x => 2}, lmap! {1 => 1}),
92 (lmap! {x => 2}, lmap! {1 => 2, x => 4}),
93 ];
94 for (a, b) in cases {
95 let goal: Goal<Collections> = is_subset(&a, &b);
96 if goal.iter_resolved().count() != 0 {
97 panic!("is_subset erroneously succeeded on {:?} {:?}", a, b);
98 }
99 }
100 }
101
102 #[test]
103 fn is_superset_should_succeed_on() {
104 let x = var();
105 let cases = vec![
106 (lmap! {1 => 2}, lmap! {1 => 2}),
107 (lmap! {1 => 2, 3 => 4}, lmap! {1 => 2}),
108 (lmap! {x => 2, 3 => 4}, lmap! {x => 2}),
109 ];
110 for (a, b) in cases {
111 let goal: Goal<Collections> = is_superset(&a, &b);
112 if goal.iter_resolved().count() != 1 {
113 panic!("is_superset failed on {:?} {:?}", a, b);
114 }
115 }
116 }
117
118 #[test]
119 fn is_superset_should_fail_on() {
120 let x = var();
121 let cases = vec![
122 (lmap! {1 => 2}, lmap! {1 => 2, 3 => 4}),
123 (lmap! {x => 2}, lmap! {1 => 1}),
124 (lmap! {1 => 2, x => 4}, lmap! {x => 2}),
125 ];
126 for (a, b) in cases {
127 let goal: Goal<Collections> = is_superset(&a, &b);
128 if goal.iter_resolved().count() != 0 {
129 panic!("is_superset erroneously succeeded on {:?} {:?}", a, b);
130 }
131 }
132 }
133}