diff --git a/src/flow/traversible.rs b/src/flow/traversible.rs index 357e7e2..5be1623 100644 --- a/src/flow/traversible.rs +++ b/src/flow/traversible.rs @@ -1,5 +1,6 @@ //! Traversible binary trees. +pub mod algorithms; pub mod unbalanced; use std::rc::Rc; @@ -66,127 +67,3 @@ pub trait TraversibleBinaryReference<'a, T: 'a + Monad, A: 'a, D: 'a + PartialEq pub trait TraversibleBinaryTree<'a, T: 'a + Monad, A: 'a, D: 'a + PartialEq>: 'a { fn refer(&self) -> Option>>; } - -pub fn n_contains<'a, T: 'a + MonadFail<()>, A: 'a, D: 'a + PartialEq>( - comparator: &'a dyn Comparator, - n_set: Rc>, - key: Rc, -) -> T::F<'a, ()> { - let (t_setl, t_setr, k_set) = n_set.split(); - match comparator.pick_smaller(key.as_ref(), k_set.as_ref()) { - Comparison::L => t_contains(comparator, t_setl, key), - Comparison::E => T::pure(()), - Comparison::R => t_contains(comparator, t_setr, key), - } -} - -pub fn r_contains<'a, T: 'a + MonadFail<()>, A: 'a, D: 'a + PartialEq>( - comparator: &'a dyn Comparator, - r_set: Rc>, - key: Rc, -) -> T::F<'a, ()> { - T::bind(r_set.resolve(), |n_set| n_contains(comparator, n_set, key)) -} - -pub fn t_contains<'a, T: 'a + MonadFail<()>, A: 'a, D: 'a + PartialEq>( - comparator: &'a dyn Comparator, - t_set: Rc>, - key: Rc, -) -> T::F<'a, ()> { - match t_set.refer() { - Some(r_set) => r_contains(comparator, r_set, key), - None => T::fail(()), - } -} - -pub fn n_subset_of_n<'a, T: 'a + MonadFail<()>, A: 'a, D: 'a + PartialEq>( - comparator: &'a dyn Comparator, - n_subset: Rc>, - n_superset: Rc>, - k_l: Option>, - k_r: Option>, -) -> T::F<'a, ()> { - let (t_superl, t_superr, k_super) = n_superset.split(); - if let Some(ref a_l) = k_l { - if let Comparison::R = comparator.pick_smaller(a_l.as_ref(), k_super.as_ref()) { - return t_subset_of_t(comparator, n_subset.to_tree(), t_superr, k_l, k_r); - } - } - if let Some(ref a_r) = k_r { - if let Comparison::L = comparator.pick_smaller(a_r.as_ref(), k_super.as_ref()) { - return t_subset_of_t(comparator, n_subset.to_tree(), t_superl, k_l, k_r); - } - } - let (t_subl, t_subr, k_sub) = n_subset.split(); - match comparator.pick_smaller(k_sub.as_ref(), k_super.as_ref()) { - Comparison::L => T::la2( - and, - t_contains(comparator, t_superl.clone(), k_sub.clone()), - T::la2( - and, - t_subset_of_t(comparator, t_subl, t_superl, k_l, Some(k_sub.clone())), - t_subset_of_t( - comparator, - t_subr, - n_superset.to_tree(), - Some(k_sub.clone()), - k_r, - ), - ), - ), - Comparison::E => T::la2( - and, - t_subset_of_t(comparator, t_subl, t_superl, k_l, Some(k_sub.clone())), - t_subset_of_t(comparator, t_subr, t_superr, Some(k_sub.clone()), k_r), - ), - Comparison::R => T::la2( - and, - t_contains(comparator, t_superr.clone(), k_sub.clone()), - T::la2( - and, - t_subset_of_t( - comparator, - t_subl, - n_superset.to_tree(), - k_l, - Some(k_sub.clone()), - ), - t_subset_of_t(comparator, t_subr, t_superr, Some(k_sub.clone()), k_r), - ), - ), - } -} - -pub fn r_subset_of_r<'a, T: 'a + MonadFail<()>, A: 'a, D: 'a + PartialEq>( - comparator: &'a dyn Comparator, - r_subset: Rc>, - r_superset: Rc>, - k_l: Option>, - k_r: Option>, -) -> T::F<'a, ()> { - T::join(T::la2( - move |n_subset, n_superset| n_subset_of_n(comparator, n_subset, n_superset, k_l, k_r), - r_subset.resolve(), - r_superset.resolve(), - )) -} - -pub fn t_subset_of_t<'a, T: MonadFail<()>, A, D: 'a + PartialEq>( - comparator: &'a dyn Comparator, - t_subset: Rc>, - t_superset: Rc>, - k_l: Option>, - k_r: Option>, -) -> T::F<'a, ()> { - match (t_subset.refer(), t_superset.refer()) { - (None, _) => T::pure(()), - (Some(_), None) => T::fail(()), - (Some(r_subset), Some(r_superset)) => { - if r_subset.data() == r_superset.data() { - T::pure(()) - } else { - r_subset_of_r(comparator, r_subset, r_superset, k_l, k_r) - } - } - } -} diff --git a/src/flow/traversible/algorithms.rs b/src/flow/traversible/algorithms.rs new file mode 100644 index 0000000..5b12cee --- /dev/null +++ b/src/flow/traversible/algorithms.rs @@ -0,0 +1,2 @@ +pub mod contains; +pub mod subset; diff --git a/src/flow/traversible/algorithms/contains.rs b/src/flow/traversible/algorithms/contains.rs new file mode 100644 index 0000000..4b299ea --- /dev/null +++ b/src/flow/traversible/algorithms/contains.rs @@ -0,0 +1,33 @@ +use crate::flow::traversible::*; + +pub fn n_contains<'a, T: 'a + MonadFail<()>, A: 'a, D: 'a + PartialEq>( + comparator: &'a dyn Comparator, + n_set: Rc>, + key: Rc, +) -> T::F<'a, ()> { + let (t_setl, t_setr, k_set) = n_set.split(); + match comparator.pick_smaller(key.as_ref(), k_set.as_ref()) { + Comparison::L => t_contains(comparator, t_setl, key), + Comparison::E => T::pure(()), + Comparison::R => t_contains(comparator, t_setr, key), + } +} + +pub fn r_contains<'a, T: 'a + MonadFail<()>, A: 'a, D: 'a + PartialEq>( + comparator: &'a dyn Comparator, + r_set: Rc>, + key: Rc, +) -> T::F<'a, ()> { + T::bind(r_set.resolve(), |n_set| n_contains(comparator, n_set, key)) +} + +pub fn t_contains<'a, T: 'a + MonadFail<()>, A: 'a, D: 'a + PartialEq>( + comparator: &'a dyn Comparator, + t_set: Rc>, + key: Rc, +) -> T::F<'a, ()> { + match t_set.refer() { + Some(r_set) => r_contains(comparator, r_set, key), + None => T::fail(()), + } +} diff --git a/src/flow/traversible/algorithms/subset.rs b/src/flow/traversible/algorithms/subset.rs new file mode 100644 index 0000000..1066782 --- /dev/null +++ b/src/flow/traversible/algorithms/subset.rs @@ -0,0 +1,159 @@ +use crate::flow::traversible::*; + +struct SubsetContext<'a, T: 'a + MonadFail<()>, A: 'a, D: 'a + PartialEq> { + comparator: &'a dyn Comparator, + n_subset: Rc>, + n_superset: Rc>, + k_l: Option>, + k_r: Option>, + t_superl: Rc>, + t_superr: Rc>, + k_super: Rc, +} + +impl<'a, T: 'a + MonadFail<()>, A: 'a, D: 'a + PartialEq> SubsetContext<'a, T, A, D> { + fn on_l(self, (t_subl, t_subr, k_sub): Split<'a, T, A, D>) -> T::F<'a, ()> { + T::la2( + and, + algorithms::contains::t_contains(self.comparator, self.t_superl.clone(), k_sub.clone()), + T::la2( + and, + t_subset_of_t( + self.comparator, + t_subl, + self.t_superl, + self.k_l, + Some(k_sub.clone()), + ), + t_subset_of_t( + self.comparator, + t_subr, + self.n_superset.to_tree(), + Some(k_sub.clone()), + self.k_r, + ), + ), + ) + } + + fn on_e(self, (t_subl, t_subr, k_sub): Split<'a, T, A, D>) -> T::F<'a, ()> { + T::la2( + and, + t_subset_of_t( + self.comparator, + t_subl, + self.t_superl, + self.k_l, + Some(k_sub.clone()), + ), + t_subset_of_t( + self.comparator, + t_subr, + self.t_superr, + Some(k_sub.clone()), + self.k_r, + ), + ) + } + + fn on_r(self, (t_subl, t_subr, k_sub): Split<'a, T, A, D>) -> T::F<'a, ()> { + T::la2( + and, + algorithms::contains::t_contains(self.comparator, self.t_superr.clone(), k_sub.clone()), + T::la2( + and, + t_subset_of_t( + self.comparator, + t_subl, + self.n_superset.to_tree(), + self.k_l, + Some(k_sub.clone()), + ), + t_subset_of_t( + self.comparator, + t_subr, + self.t_superr, + Some(k_sub.clone()), + self.k_r, + ), + ), + ) + } + + fn test(self) -> T::F<'a, ()> { + let split = self.n_subset.split(); + match self + .comparator + .pick_smaller(split.2.as_ref(), self.k_super.as_ref()) + { + Comparison::L => self.on_l(split), + Comparison::E => self.on_e(split), + Comparison::R => self.on_r(split), + } + } +} + +pub fn n_subset_of_n<'a, T: 'a + MonadFail<()>, A: 'a, D: 'a + PartialEq>( + comparator: &'a dyn Comparator, + n_subset: Rc>, + n_superset: Rc>, + k_l: Option>, + k_r: Option>, +) -> T::F<'a, ()> { + let (t_superl, t_superr, k_super) = n_superset.split(); + if let Some(ref a_l) = k_l { + if let Comparison::R = comparator.pick_smaller(a_l.as_ref(), k_super.as_ref()) { + return t_subset_of_t(comparator, n_subset.to_tree(), t_superr, k_l, k_r); + } + } + if let Some(ref a_r) = k_r { + if let Comparison::L = comparator.pick_smaller(a_r.as_ref(), k_super.as_ref()) { + return t_subset_of_t(comparator, n_subset.to_tree(), t_superl, k_l, k_r); + } + } + SubsetContext { + comparator, + n_subset, + n_superset, + k_l, + k_r, + t_superl, + t_superr, + k_super, + } + .test() +} + +pub fn r_subset_of_r<'a, T: 'a + MonadFail<()>, A: 'a, D: 'a + PartialEq>( + comparator: &'a dyn Comparator, + r_subset: Rc>, + r_superset: Rc>, + k_l: Option>, + k_r: Option>, +) -> T::F<'a, ()> { + T::join(T::la2( + move |n_subset, n_superset| n_subset_of_n(comparator, n_subset, n_superset, k_l, k_r), + r_subset.resolve(), + r_superset.resolve(), + )) +} + +pub fn t_subset_of_t<'a, T: MonadFail<()>, A, D: 'a + PartialEq>( + comparator: &'a dyn Comparator, + t_subset: Rc>, + t_superset: Rc>, + k_l: Option>, + k_r: Option>, +) -> T::F<'a, ()> { + match (t_subset.refer(), t_superset.refer()) { + (None, _) => T::pure(()), + (Some(_), None) => T::fail(()), + (Some(r_subset), Some(r_superset)) => { + if r_subset.data() == r_superset.data() { + T::pure(()) + } else { + r_subset_of_r(comparator, r_subset, r_superset, k_l, k_r) + } + } + } +} diff --git a/src/flow/traversible/unbalanced.rs b/src/flow/traversible/unbalanced.rs index aab785c..9b58b5a 100644 --- a/src/flow/traversible/unbalanced.rs +++ b/src/flow/traversible/unbalanced.rs @@ -175,7 +175,7 @@ mod tests { use crate::std::tracing::*; - use super::*; + use super::{algorithms::contains::*, algorithms::subset::*, *}; #[test] fn test_simple_slices() {