From 911e536c67af341fffdd0f2ef900b1780af7ac2c Mon Sep 17 00:00:00 2001 From: timofey Date: Mon, 24 Apr 2023 22:11:52 +0000 Subject: [PATCH] flow::traversible --- src/flow.rs | 1 + src/flow/traversible.rs | 164 ++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/std/local_origin.rs | 16 ++-- src/std/nullable.rs | 22 +++++- 5 files changed, 197 insertions(+), 7 deletions(-) create mode 100644 src/flow.rs create mode 100644 src/flow/traversible.rs diff --git a/src/flow.rs b/src/flow.rs new file mode 100644 index 0000000..92e6c1d --- /dev/null +++ b/src/flow.rs @@ -0,0 +1 @@ +pub mod traversible; diff --git a/src/flow/traversible.rs b/src/flow/traversible.rs new file mode 100644 index 0000000..8f0ed80 --- /dev/null +++ b/src/flow/traversible.rs @@ -0,0 +1,164 @@ +use std::rc::Rc; + +use crate::func::*; + +pub enum Comparison { + L, + E, + R, +} + +fn and(left: bool, right: bool) -> bool { + left && right +} + +pub trait Comparator { + fn pick_smaller(&self, kl: &A, kr: &A) -> Comparison; +} + +pub type Split<'a, T, A, D> = ( + Rc>, + Rc>, + Rc, +); + +pub trait TraversibleBinaryNode<'a, T: Monad, A, D: 'a + PartialEq>: 'a { + fn split(&self) -> Split<'a, T, A, D>; + + fn to_tree(self: Rc) -> Rc>; +} + +pub trait TraversibleBinaryReference<'a, T: Monad, A, D: 'a + PartialEq>: 'a { + fn resolve(&self) -> ::F<'a, Rc>>; + + /// This should be enough to compare reference for equality. + fn data(&self) -> D; +} + +pub trait TraversibleBinaryTree<'a, T: Monad, A, D: 'a + PartialEq>: 'a { + fn refer(&self) -> Option>>; +} + +pub fn n_contains<'a, T: Monad, A, D: 'a + PartialEq>( + comparator: &'a dyn Comparator, + n_set: Rc>, + key: Rc, +) -> T::F<'a, bool> { + 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(true), + Comparison::R => t_contains(comparator, t_setr, key), + } +} + +pub fn r_contains<'a, T: Monad, A, D: 'a + PartialEq>( + comparator: &'a dyn Comparator, + r_set: Rc>, + key: Rc, +) -> T::F<'a, bool> { + T::bind(r_set.resolve(), |n_set| n_contains(comparator, n_set, key)) +} + +pub fn t_contains<'a, T: Monad, A, D: 'a + PartialEq>( + comparator: &'a dyn Comparator, + t_set: Rc>, + key: Rc, +) -> T::F<'a, bool> { + match t_set.refer() { + Some(r_set) => r_contains(comparator, r_set, key), + None => T::pure(false), + } +} + +pub fn n_subset_of_n<'a, T: Monad, A, D: 'a + PartialEq>( + comparator: &'a dyn Comparator, + n_subset: Rc>, + n_superset: Rc>, + k_l: Option>, + k_r: Option>, +) -> T::F<'a, bool> { + 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_subset.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_subset.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: Monad, A, D: 'a + PartialEq>( + comparator: &'a dyn Comparator, + r_subset: Rc>, + r_superset: Rc>, + k_l: Option>, + k_r: Option>, +) -> T::F<'a, bool> { + 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: Monad, A, D: 'a + PartialEq>( + comparator: &'a dyn Comparator, + t_subset: Rc>, + t_superset: Rc>, + k_l: Option>, + k_r: Option>, +) -> T::F<'a, bool> { + match (t_subset.refer(), t_superset.refer()) { + (None, _) => T::pure(true), + (Some(_), None) => T::pure(false), + (Some(r_subset), Some(r_superset)) => { + if r_subset.data() == r_superset.data() { + T::pure(true) + } else { + r_subset_of_r(comparator, r_subset, r_superset, k_l, k_r) + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index ab75570..e91b794 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ pub mod core; +pub mod flow; pub mod func; pub mod std; #[cfg(test)] diff --git a/src/std/local_origin.rs b/src/std/local_origin.rs index 3beb310..25aaac7 100644 --- a/src/std/local_origin.rs +++ b/src/std/local_origin.rs @@ -19,7 +19,7 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> { Self::from_fields(point, Rc::new(origin)) } - fn from_mentionable(mentionable: A) -> Self { + fn from_mentionable(mentionable: Rc) -> Self { Self::from_values( Ctx::hash(&Self::prepare_bytes_for_hashing(&mentionable)), LocalOrigin::from(mentionable), @@ -41,14 +41,20 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Origin<'a, Ctx> for LocalOr } } -impl From for LocalOrigin { - fn from(value: A) -> Self { - LocalOrigin(value.into()) +impl From> for LocalOrigin { + fn from(value: Rc) -> Self { + LocalOrigin(value) + } +} + +impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> From> for Point<'a, Ctx, A> { + fn from(value: Rc) -> Self { + Self::from_mentionable(value) } } impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> From for Point<'a, Ctx, A> { fn from(value: A) -> Self { - Self::from_mentionable(value) + Self::from_mentionable(value.into()) } } diff --git a/src/std/nullable.rs b/src/std/nullable.rs index 537b49c..f560ec4 100644 --- a/src/std/nullable.rs +++ b/src/std/nullable.rs @@ -78,15 +78,21 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Nullable<'a, Ctx, Nullable< /// Reduce [Nullable] nesting. pub fn join(&self) -> Resolution<'a, Ctx, Nullable<'a, Ctx, A>> { match self { - Nullable::Null(nullable_factory) => { + Self::Null(nullable_factory) => { let NullableFactory { factory } = nullable_factory; Ctx::T::pure(Ok(Rc::new(Nullable::Null(factory.clone())))) } - Nullable::NotNull(point) => point.resolve(), + Self::NotNull(point) => point.resolve(), } } } +impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Nullable<'a, Ctx, A> { + fn from_mentionable(mentionable: Rc) -> Self { + Self::NotNull(mentionable.into()) + } +} + impl NullableFactory { pub fn new(factory: F) -> Self { Self { factory } @@ -105,3 +111,15 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Clone for Nullable<'a, Ctx, impl AlwaysConstSize for NullableFactory { const _SIZE: usize = HASH_SIZE; } + +impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> From> for Nullable<'a, Ctx, A> { + fn from(value: Rc) -> Self { + Self::from_mentionable(value) + } +} + +impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> From for Nullable<'a, Ctx, A> { + fn from(value: A) -> Self { + Self::from_mentionable(value.into()) + } +}