BinaryTreesAvl
This commit is contained in:
parent
beefedaf2b
commit
f5cbf65df9
@ -1,20 +1,21 @@
|
||||
mod avl;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::func::*;
|
||||
use crate::{flow::comparator::*, func::*};
|
||||
|
||||
use super::comparator::Comparator;
|
||||
|
||||
pub type NodeRc<'a, BT> = Rc<<BT as BinaryTrees<'a>>::Node>;
|
||||
pub type ReferenceRc<'a, BT> = Rc<<BT as BinaryTrees<'a>>::Reference>;
|
||||
pub type TreeRc<'a, BT> = Rc<<BT as BinaryTrees<'a>>::Tree>;
|
||||
pub type KeyRc<'a, BT> = Rc<<BT as BinaryTrees<'a>>::Key>;
|
||||
|
||||
pub type Split<'a, BT> = (TreeRc<'a, BT>, TreeRc<'a, BT>, KeyRc<'a, BT>);
|
||||
pub type KeySplit<'a, BT> = (TreeRc<'a, BT>, TreeRc<'a, BT>);
|
||||
pub type Split<'a, BT> = (
|
||||
<BT as BinaryTrees<'a>>::Tree,
|
||||
<BT as BinaryTrees<'a>>::Tree,
|
||||
KeyRc<'a, BT>,
|
||||
);
|
||||
pub type KeySplit<'a, BT> = (<BT as BinaryTrees<'a>>::Tree, <BT as BinaryTrees<'a>>::Tree);
|
||||
|
||||
pub type BTWrap<'a, BT, A> = Wrap<'a, A, <BT as BinaryTrees<'a>>::T>;
|
||||
|
||||
pub trait BinaryTrees<'a>: 'a {
|
||||
pub trait BinaryTrees<'a>: 'a + Clone {
|
||||
type Node: 'a;
|
||||
type Reference: 'a;
|
||||
type Tree: 'a;
|
||||
@ -25,24 +26,188 @@ pub trait BinaryTrees<'a>: 'a {
|
||||
|
||||
fn comparator(&self) -> &Self::Comparator;
|
||||
fn split(&self, node: &Self::Node) -> Split<'a, Self>;
|
||||
fn tree_of(&self, node: Self::Node) -> BTWrap<'a, Self, TreeRc<'a, Self>>;
|
||||
fn resolve(&self, reference: &Self::Reference) -> BTWrap<'a, Self, NodeRc<'a, Self>>;
|
||||
fn tree_of(&self, node: Self::Node) -> BTWrap<'a, Self, Self::Tree>;
|
||||
fn resolve(&self, reference: &Self::Reference) -> BTWrap<'a, Self, Self::Node>;
|
||||
fn equal(&self, rhs: &Self::Reference, lhs: &Self::Reference) -> bool;
|
||||
fn refer(&self, tree: &Self::Tree) -> Option<ReferenceRc<'a, Self>>;
|
||||
fn refer(&self, tree: &Self::Tree) -> Option<Self::Reference>;
|
||||
}
|
||||
|
||||
pub trait BinaryTreesMutable<'a>: BinaryTrees<'a> {
|
||||
fn empty(&self) -> Self::Tree;
|
||||
|
||||
fn join_key(
|
||||
&self,
|
||||
self,
|
||||
tl: Self::Tree,
|
||||
key: KeyRc<'a, Self>,
|
||||
tr: Self::Tree,
|
||||
) -> BTWrap<'a, Self, NodeRc<'a, Self>>;
|
||||
fn join(&self, tl: Self::Tree, tr: Self::Tree) -> BTWrap<'a, Self, TreeRc<'a, Self>>;
|
||||
fn split_key(
|
||||
) -> BTWrap<'a, Self, Self::Node>;
|
||||
|
||||
fn join_key_tree(
|
||||
self,
|
||||
tl: Self::Tree,
|
||||
key: KeyRc<'a, Self>,
|
||||
tr: Self::Tree,
|
||||
) -> BTWrap<'a, Self, Self::Tree> {
|
||||
<Self::T as Monad>::bind(self.clone().join_key(tl, key, tr), move |n| self.tree_of(n))
|
||||
}
|
||||
|
||||
fn join(&self, tl: Self::Tree, tr: Self::Tree) -> BTWrap<'a, Self, Self::Tree> {
|
||||
let Some(rl) = self.refer(&tl) else {
|
||||
return <Self::T as Pure>::pure(tr)
|
||||
};
|
||||
let Some(rr) = self.refer(&tr) else {
|
||||
return <Self::T as Pure>::pure(tl)
|
||||
};
|
||||
let ctx = self.clone();
|
||||
<Self::T as Monad>::join(<Self::T as ApplicativeLA2>::la2(
|
||||
move |nl, nr| {
|
||||
let (tll, tlr, kl) = ctx.split(&nl);
|
||||
let (trl, trr, kr) = ctx.split(&nr);
|
||||
let ft = ctx.join(tlr, trl);
|
||||
let ft = {
|
||||
let ctx = ctx.clone();
|
||||
<Self::T as Monad>::bind(ft, move |t| ctx.join_key_tree(tll, kl, t))
|
||||
};
|
||||
let ft = {
|
||||
let ctx = ctx.clone();
|
||||
<Self::T as Monad>::bind(ft, move |t| ctx.join_key_tree(t, kr, trr))
|
||||
};
|
||||
ft
|
||||
},
|
||||
self.resolve(&rl),
|
||||
self.resolve(&rr),
|
||||
))
|
||||
}
|
||||
|
||||
fn split_key_empty(
|
||||
&self,
|
||||
tree: Self::Tree,
|
||||
key: KeyRc<'a, Self>,
|
||||
) -> BTWrap<'a, Self, KeySplit<'a, Self>>;
|
||||
|
||||
fn split_key_node(
|
||||
self,
|
||||
node: Self::Node,
|
||||
key: KeyRc<'a, Self>,
|
||||
) -> BTWrap<'a, Self, KeySplit<'a, Self>> {
|
||||
let (tl, tr, k) = self.split(&node);
|
||||
match self.comparator().pick_smaller(&key, &k) {
|
||||
Comparison::L => {
|
||||
<Self::T as Monad>::bind(self.clone().split_key(tl, key), move |(tll, tlr)| {
|
||||
<Self::T as Functor>::fmap(|t| (tll, t), self.join_key_tree(tlr, k, tr))
|
||||
})
|
||||
}
|
||||
Comparison::E => <Self::T as Pure>::pure((tl, tr)),
|
||||
Comparison::R => {
|
||||
<Self::T as Monad>::bind(self.clone().split_key(tr, key), move |(trl, trr)| {
|
||||
<Self::T as Functor>::fmap(|t| (t, trr), self.join_key_tree(tl, k, trl))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn split_key(
|
||||
self,
|
||||
tree: Self::Tree,
|
||||
key: KeyRc<'a, Self>,
|
||||
) -> BTWrap<'a, Self, KeySplit<'a, Self>> {
|
||||
match self.refer(&tree) {
|
||||
Some(reference) => <Self::T as Monad>::bind(self.resolve(&reference), |node| {
|
||||
self.split_key_node(node, key)
|
||||
}),
|
||||
None => self.split_key_empty(tree, key),
|
||||
}
|
||||
}
|
||||
|
||||
fn add(self, tree: Self::Tree, key: KeyRc<'a, Self>) -> BTWrap<'a, Self, Self::Node> {
|
||||
<Self::T as Monad>::bind(self.clone().split_key(tree, key.clone()), |(tl, tr)| {
|
||||
self.join_key(tl, key, tr)
|
||||
})
|
||||
}
|
||||
|
||||
fn add_tree(self, tree: Self::Tree, key: KeyRc<'a, Self>) -> BTWrap<'a, Self, Self::Tree> {
|
||||
<Self::T as Monad>::bind(self.clone().add(tree, key), move |n| self.tree_of(n))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait BinaryTreesAvl<'a>: BinaryTrees<'a> {
|
||||
fn height(&self, tree: &Self::Tree) -> u64;
|
||||
|
||||
fn leaf_height_error<T: 'a>(&self, height: u64) -> BTWrap<'a, Self, T>;
|
||||
|
||||
fn assume_node(&self, tree: &Self::Tree) -> BTWrap<'a, Self, Self::Node> {
|
||||
match self.refer(tree) {
|
||||
Some(reference) => self.resolve(&reference),
|
||||
None => self.leaf_height_error(self.height(tree)),
|
||||
}
|
||||
}
|
||||
|
||||
fn join_key_unbalanced(
|
||||
&self,
|
||||
tl: Self::Tree,
|
||||
key: KeyRc<'a, Self>,
|
||||
tr: Self::Tree,
|
||||
) -> BTWrap<'a, Self, Self::Node>;
|
||||
|
||||
fn join_key_balanced_tree(
|
||||
self,
|
||||
tl: Self::Tree,
|
||||
key: KeyRc<'a, Self>,
|
||||
tr: Self::Tree,
|
||||
) -> BTWrap<'a, Self, Self::Tree> {
|
||||
<Self::T as Monad>::bind(self.clone().join_key_balanced(tl, key, tr), move |node| {
|
||||
self.tree_of(node)
|
||||
})
|
||||
}
|
||||
|
||||
fn join_key_balanced(
|
||||
self,
|
||||
tl: Self::Tree,
|
||||
key: KeyRc<'a, Self>,
|
||||
tr: Self::Tree,
|
||||
) -> BTWrap<'a, Self, Self::Node> {
|
||||
let (lh, rh) = (self.height(&tl), self.height(&tr));
|
||||
match (lh.saturating_sub(rh), rh.saturating_sub(lh)) {
|
||||
(0, 0) | (0, 1) | (1, 0) => self.join_key_unbalanced(tl, key, tr),
|
||||
(0, _) => <Self::T as Monad>::bind(self.assume_node(&tr), move |nr| {
|
||||
let (trl, trr, kr) = self.split(&nr);
|
||||
let (rlh, rrh) = (self.height(&trl), self.height(&trr));
|
||||
if rlh > rrh {
|
||||
<Self::T as Monad>::bind(self.assume_node(&trl), move |nrl| {
|
||||
let (trll, trlr, krl) = self.split(&nrl);
|
||||
Self::T::bind2(
|
||||
self.clone().join_key_balanced_tree(tl, key, trll),
|
||||
self.clone().join_key_balanced_tree(trlr, kr, trr),
|
||||
|ti, to| self.join_key_balanced(ti, krl, to),
|
||||
)
|
||||
})
|
||||
} else {
|
||||
<Self::T as Monad>::bind(
|
||||
self.clone().join_key_balanced_tree(tl, key, trl),
|
||||
|t| self.join_key_balanced(t, kr, trr),
|
||||
)
|
||||
}
|
||||
}),
|
||||
(_, 0) => <Self::T as Monad>::bind(self.assume_node(&tl), move |nl| {
|
||||
let (tll, tlr, kl) = self.split(&nl);
|
||||
let (llh, lrh) = (self.height(&tll), self.height(&tlr));
|
||||
if llh < lrh {
|
||||
<Self::T as Monad>::bind(self.assume_node(&tlr), move |nlr| {
|
||||
let (tlrl, tlrr, klr) = self.split(&nlr);
|
||||
Self::T::bind2(
|
||||
self.clone().join_key_balanced_tree(tll, kl, tlrl),
|
||||
self.clone().join_key_balanced_tree(tlrr, key, tr),
|
||||
|to, ti| self.join_key_balanced(to, klr, ti),
|
||||
)
|
||||
})
|
||||
} else {
|
||||
<Self::T as Monad>::bind(
|
||||
self.clone().join_key_balanced_tree(tlr, key, tr),
|
||||
|t| self.join_key_balanced(tll, kl, t),
|
||||
)
|
||||
}
|
||||
}),
|
||||
(_, _) => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
172
src/flow/binary/avl.rs
Normal file
172
src/flow/binary/avl.rs
Normal file
@ -0,0 +1,172 @@
|
||||
use std::{fmt::Display, marker::PhantomData, rc::Rc};
|
||||
|
||||
use crate::flow::comparator::*;
|
||||
|
||||
use super::*;
|
||||
|
||||
struct AvlN<A> {
|
||||
l: AvlT<A>,
|
||||
r: AvlT<A>,
|
||||
key: Rc<A>,
|
||||
}
|
||||
|
||||
impl<A> Clone for AvlN<A> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
l: self.l.clone(),
|
||||
r: self.r.clone(),
|
||||
key: self.key.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Display> Display for AvlN<A> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_fmt(format_args!("({} {} {})", self.l, self.key, self.r))
|
||||
}
|
||||
}
|
||||
|
||||
struct AvlR<A> {
|
||||
node: Rc<AvlN<A>>,
|
||||
}
|
||||
|
||||
impl<A> Clone for AvlR<A> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
node: self.node.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Display> Display for AvlR<A> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_fmt(format_args!("{}", self.node))
|
||||
}
|
||||
}
|
||||
|
||||
struct AvlT<A> {
|
||||
reference: Option<AvlR<A>>,
|
||||
height: u64,
|
||||
}
|
||||
|
||||
impl<A> Clone for AvlT<A> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
reference: self.reference.clone(),
|
||||
height: self.height,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Display> Display for AvlT<A> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match &self.reference {
|
||||
Some(reference) => f.write_fmt(format_args!("{}", reference)),
|
||||
None => f.write_fmt(format_args!("-")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct AvlTs<A> {
|
||||
_a: PhantomData<A>,
|
||||
}
|
||||
|
||||
impl<A> AvlTs<A> {
|
||||
fn new() -> Self {
|
||||
Self { _a: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> Clone for AvlTs<A> {
|
||||
fn clone(&self) -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, A: 'a + PartialOrd> BinaryTrees<'a> for AvlTs<A> {
|
||||
type Node = AvlN<A>;
|
||||
|
||||
type Reference = AvlR<A>;
|
||||
|
||||
type Tree = AvlT<A>;
|
||||
|
||||
type Key = A;
|
||||
|
||||
type Comparator = DefaultComparator;
|
||||
|
||||
type T = instances::solo::SoloInstance;
|
||||
|
||||
fn comparator(&self) -> &Self::Comparator {
|
||||
&DefaultComparator
|
||||
}
|
||||
|
||||
fn split(&self, node: &Self::Node) -> Split<'a, Self> {
|
||||
(node.l.clone(), node.r.clone(), node.key.clone())
|
||||
}
|
||||
|
||||
fn tree_of(&self, node: Self::Node) -> BTWrap<'a, Self, Self::Tree> {
|
||||
AvlT {
|
||||
height: std::cmp::max(node.l.height, node.r.height)
|
||||
.checked_add(1)
|
||||
.unwrap(),
|
||||
reference: Some(AvlR { node: node.into() }),
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve(&self, reference: &Self::Reference) -> BTWrap<'a, Self, Self::Node> {
|
||||
reference.node.as_ref().clone()
|
||||
}
|
||||
|
||||
fn equal(&self, _rhs: &Self::Reference, _lhs: &Self::Reference) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn refer(&self, tree: &Self::Tree) -> Option<Self::Reference> {
|
||||
tree.reference.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, A: 'a + PartialOrd> BinaryTreesMutable<'a> for AvlTs<A> {
|
||||
fn empty(&self) -> Self::Tree {
|
||||
AvlT {
|
||||
reference: None,
|
||||
height: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn join_key(
|
||||
self,
|
||||
tl: Self::Tree,
|
||||
key: KeyRc<'a, Self>,
|
||||
tr: Self::Tree,
|
||||
) -> BTWrap<'a, Self, Self::Node> {
|
||||
self.join_key_balanced(tl, key, tr)
|
||||
}
|
||||
|
||||
fn split_key_empty(
|
||||
&self,
|
||||
_tree: Self::Tree,
|
||||
_key: KeyRc<'a, Self>,
|
||||
) -> BTWrap<'a, Self, KeySplit<'a, Self>> {
|
||||
(self.empty(), self.empty())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, A: 'a + PartialOrd> BinaryTreesAvl<'a> for AvlTs<A> {
|
||||
fn height(&self, tree: &Self::Tree) -> u64 {
|
||||
tree.height
|
||||
}
|
||||
|
||||
fn leaf_height_error<T: 'a>(&self, height: u64) -> BTWrap<'a, Self, T> {
|
||||
panic!("leaf height error: {height}.")
|
||||
}
|
||||
|
||||
fn join_key_unbalanced(
|
||||
&self,
|
||||
tl: Self::Tree,
|
||||
key: KeyRc<'a, Self>,
|
||||
tr: Self::Tree,
|
||||
) -> BTWrap<'a, Self, Self::Node> {
|
||||
AvlN { l: tl, r: tr, key }
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ pub enum Comparison {
|
||||
/// Returns [`Comparison`] saying which value is smaller.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use radn_rs::flow::traversible::*;
|
||||
/// # use radn_rs::flow::comparator::*;
|
||||
/// assert_eq!(DefaultComparator.pick_smaller(&1, &3), Comparison::L);
|
||||
/// assert_eq!(DefaultComparator.pick_smaller(&2, &2), Comparison::E);
|
||||
/// assert_eq!(DefaultComparator.pick_smaller(&3, &1), Comparison::R);
|
||||
|
@ -148,6 +148,14 @@ pub trait MonadExt<'a>: Monad<'a> {
|
||||
) -> Self::F<B> {
|
||||
Self::iterate(BindableMut::new(a, f))
|
||||
}
|
||||
|
||||
fn bind2<A: 'a, B: 'a, C: 'a>(
|
||||
fa: Self::F<A>,
|
||||
fb: Self::F<B>,
|
||||
f: impl 'a + FnOnce(A, B) -> Self::F<C>,
|
||||
) -> Self::F<C> {
|
||||
Self::join(Self::la2(f, fa, fb))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Monad<'a>> MonadExt<'a> for T {}
|
||||
|
20
src/rstd.rs
20
src/rstd.rs
@ -36,23 +36,3 @@ impl<S: Serializable> ExtSerializable for S {
|
||||
vec
|
||||
}
|
||||
}
|
||||
|
||||
/// Extention trait for simpler conversion between [`Context::T`] and [`Context::Fallible`].
|
||||
///
|
||||
/// Until either Rust type system or [`crate::func`] take serious changes,
|
||||
/// this is the preferred way to switch between [Wrapped] and [fallible].
|
||||
pub trait FallibleContext<'a>: Context<'a> {
|
||||
/// Convert a fallible wrapped into a wrapped result.
|
||||
fn unstuff<A: 'a, E: 'a>(
|
||||
wa: WrapE<'a, A, E, Self::Fallible>,
|
||||
) -> Wrap<'a, Result<A, E>, Self::T> {
|
||||
Self::Fallible::unstuff(wa)
|
||||
}
|
||||
|
||||
/// Convert a wrapped result into a fallible wrapped.
|
||||
fn stuff<A: 'a, E: 'a>(fa: Wrap<'a, Result<A, E>, Self::T>) -> WrapE<'a, A, E, Self::Fallible> {
|
||||
Self::Fallible::stuff(fa)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Ctx: Context<'a>> FallibleContext<'a> for Ctx {}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::{flow::comparator::*, func::*};
|
||||
use crate::flow::comparator::*;
|
||||
use crate::func::*;
|
||||
|
||||
use super::{binary::*, *};
|
||||
|
||||
@ -146,6 +147,13 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> BoundNode<'a, Ctx, A> {
|
||||
Ok(BoundTree { tree, bounds })
|
||||
}
|
||||
|
||||
pub fn into_tree_resolution(self) -> BrTree<'a, Ctx, A> {
|
||||
match self.into_tree() {
|
||||
Ok(tree) => <Ctx::T as Pure>::pure(Ok(tree)),
|
||||
Err(e) => <Ctx::T as Pure>::pure(Err(ResolutionError::Parse(e))),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
l: BoundTree<'a, Ctx, A>,
|
||||
r: BoundTree<'a, Ctx, A>,
|
||||
@ -161,7 +169,13 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> BoundNode<'a, Ctx, A> {
|
||||
}
|
||||
}
|
||||
|
||||
pub type BoundKeySplit<'a, Ctx, A> = (BoundTree<'a, Ctx, A>, BoundTree<'a, Ctx, A>);
|
||||
|
||||
impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> BoundTree<'a, Ctx, A> {
|
||||
pub fn height(&self) -> u64 {
|
||||
self.tree.height
|
||||
}
|
||||
|
||||
pub fn empty(factory: Fctr<'a, Ctx, A>) -> Self {
|
||||
Self {
|
||||
tree: AvlTree::empty(factory),
|
||||
@ -169,11 +183,44 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> BoundTree<'a, Ctx, A> {
|
||||
}
|
||||
}
|
||||
|
||||
fn empty_bound(factory: Fctr<'a, Ctx, A>, bounds: Bounds<A>) -> Self {
|
||||
Self {
|
||||
tree: AvlTree::empty(factory),
|
||||
bounds,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reference(&self) -> Option<BoundReference<'a, Ctx, A>> {
|
||||
let reference = self.tree.reference()?;
|
||||
let bounds = self.bounds.clone();
|
||||
Some(BoundReference { reference, bounds })
|
||||
}
|
||||
|
||||
fn split_empty(
|
||||
bounds: Bounds<A>,
|
||||
key: &Rc<A>,
|
||||
factory: &Fctr<'a, Ctx, A>,
|
||||
comparator: &impl Comparator<A>,
|
||||
) -> Result<(Self, Self), BoundsError<A>> {
|
||||
let (bl, br) = bounds.split(key, comparator)?;
|
||||
Ok((
|
||||
Self::empty_bound(factory.clone(), bl),
|
||||
Self::empty_bound(factory.clone(), br),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn split_empty_res(
|
||||
self,
|
||||
key: Rc<A>,
|
||||
factory: Fctr<'a, Ctx, A>,
|
||||
comparator: Rc<impl 'a + Comparator<A>>,
|
||||
) -> BrKeySplit<'a, Ctx, A> {
|
||||
<Ctx::T as Pure>::pure(
|
||||
Self::split_empty(self.bounds, &key, &factory, comparator.as_ref())
|
||||
.map_err(BoundError::Bounds)
|
||||
.map_err(ResolutionError::Parse),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Clone for BoundTree<'a, Ctx, A> {
|
||||
@ -188,13 +235,18 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Clone for BoundTree<'a, Ctx,
|
||||
pub type BoundResolutionError<'a, Ctx, A> =
|
||||
ResolutionError<<Ctx as Context<'a>>::LookupError, BoundErrorA<'a, Ctx, A>>;
|
||||
|
||||
pub type BoundResolutionResult<'a, Ctx, A> =
|
||||
Result<BoundNode<'a, Ctx, A>, BoundResolutionError<'a, Ctx, A>>;
|
||||
pub type BoundResolutionResult<'a, Ctx, A, T> = Result<T, BoundResolutionError<'a, Ctx, A>>;
|
||||
|
||||
pub type BoundResolution<'a, Ctx, A> = Wrapped<'a, Ctx, BoundResolutionResult<'a, Ctx, A>>;
|
||||
pub type BoundResolution<'a, Ctx, A, T> = Wrapped<'a, Ctx, BoundResolutionResult<'a, Ctx, A, T>>;
|
||||
|
||||
pub type BrNode<'a, Ctx, A> = BoundResolution<'a, Ctx, A, BoundNode<'a, Ctx, A>>;
|
||||
|
||||
pub type BrTree<'a, Ctx, A> = BoundResolution<'a, Ctx, A, BoundTree<'a, Ctx, A>>;
|
||||
|
||||
pub type BrKeySplit<'a, Ctx, A> = BoundResolution<'a, Ctx, A, BoundKeySplit<'a, Ctx, A>>;
|
||||
|
||||
impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> BoundReference<'a, Ctx, A> {
|
||||
pub fn resolve(&self, comparator: Rc<impl 'a + Comparator<A>>) -> BoundResolution<'a, Ctx, A> {
|
||||
pub fn resolve(&self, comparator: Rc<impl 'a + Comparator<A>>) -> BrNode<'a, Ctx, A> {
|
||||
let bounds = self.bounds.clone();
|
||||
<Ctx::T as Functor>::fmap(
|
||||
move |resolution| {
|
||||
|
111
src/rstd/collections/avl/context.rs
Normal file
111
src/rstd/collections/avl/context.rs
Normal file
@ -0,0 +1,111 @@
|
||||
use crate::flow::{binary::*, comparator::*};
|
||||
use crate::func::*;
|
||||
use crate::rstd::fallible::*;
|
||||
|
||||
use super::{bounds::*, *};
|
||||
|
||||
pub struct BoundContext<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>, C: 'a + Comparator<A>> {
|
||||
factory: A::Fctr,
|
||||
comparator: Rc<C>,
|
||||
}
|
||||
|
||||
impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>, C: 'a + Comparator<A>> Clone
|
||||
for BoundContext<'a, Ctx, A, C>
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
factory: self.factory.clone(),
|
||||
comparator: self.comparator.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>, C: 'a + Comparator<A>> BinaryTrees<'a>
|
||||
for BoundContext<'a, Ctx, A, C>
|
||||
{
|
||||
type Node = BoundNode<'a, Ctx, A>;
|
||||
type Reference = BoundReference<'a, Ctx, A>;
|
||||
type Tree = BoundTree<'a, Ctx, A>;
|
||||
type Key = A;
|
||||
type Comparator = C;
|
||||
|
||||
type T = FallibleMonad<'a, Ctx, BoundResolutionError<'a, Ctx, A>>;
|
||||
|
||||
fn comparator(&self) -> &Self::Comparator {
|
||||
&self.comparator
|
||||
}
|
||||
|
||||
fn split(&self, node: &Self::Node) -> Split<'a, Self> {
|
||||
node.split()
|
||||
}
|
||||
|
||||
fn tree_of(&self, node: Self::Node) -> BTWrap<'a, Self, Self::Tree> {
|
||||
match node.into_tree() {
|
||||
Ok(tree) => <Self::T as Pure>::pure(tree),
|
||||
Err(e) => <Self::T as Fail<_>>::fail(ResolutionError::Parse(e)),
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve(&self, reference: &Self::Reference) -> BTWrap<'a, Self, Self::Node> {
|
||||
Ctx::stuff(reference.resolve(self.comparator.clone()))
|
||||
}
|
||||
|
||||
fn equal(&self, rhs: &Self::Reference, lhs: &Self::Reference) -> bool {
|
||||
BoundReference::equal(lhs, rhs, self.comparator.as_ref())
|
||||
}
|
||||
|
||||
fn refer(&self, tree: &Self::Tree) -> Option<Self::Reference> {
|
||||
tree.reference()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>, C: 'a + Comparator<A>> BinaryTreesMutable<'a>
|
||||
for BoundContext<'a, Ctx, A, C>
|
||||
{
|
||||
fn empty(&self) -> Self::Tree {
|
||||
BoundTree::empty(self.factory.clone())
|
||||
}
|
||||
|
||||
fn join_key(
|
||||
self,
|
||||
tl: Self::Tree,
|
||||
key: KeyRc<'a, Self>,
|
||||
tr: Self::Tree,
|
||||
) -> BTWrap<'a, Self, Self::Node> {
|
||||
self.join_key_balanced(tl, key, tr)
|
||||
}
|
||||
|
||||
fn split_key_empty(
|
||||
&self,
|
||||
tree: Self::Tree,
|
||||
key: KeyRc<'a, Self>,
|
||||
) -> BTWrap<'a, Self, KeySplit<'a, Self>> {
|
||||
Ctx::stuff(tree.split_empty_res(key, self.factory.clone(), self.comparator.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>, C: 'a + Comparator<A>> BinaryTreesAvl<'a>
|
||||
for BoundContext<'a, Ctx, A, C>
|
||||
{
|
||||
fn height(&self, tree: &Self::Tree) -> u64 {
|
||||
tree.height()
|
||||
}
|
||||
|
||||
fn leaf_height_error<T: 'a>(&self, height: u64) -> BTWrap<'a, Self, T> {
|
||||
<FallibleMonad<'a, Ctx, _> as Fail<_>>::fail(ResolutionError::Parse(BoundError::Avl(
|
||||
AvlError::LeafHeight(height),
|
||||
)))
|
||||
}
|
||||
|
||||
fn join_key_unbalanced(
|
||||
&self,
|
||||
tl: Self::Tree,
|
||||
key: KeyRc<'a, Self>,
|
||||
tr: Self::Tree,
|
||||
) -> BTWrap<'a, Self, Self::Node> {
|
||||
match BoundNode::new(tl, tr, key, self.comparator.as_ref()) {
|
||||
Ok(n) => <FallibleMonad<'a, Ctx, _> as Pure>::pure(n),
|
||||
Err(e) => <FallibleMonad<'a, Ctx, _> as Fail<_>>::fail(ResolutionError::Parse(e)),
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@ use std::rc::Rc;
|
||||
|
||||
use crate::flow::traversible::*;
|
||||
use crate::func::*;
|
||||
use crate::rstd::{fallible::*, *};
|
||||
use crate::rstd::fallible::*;
|
||||
|
||||
use super::*;
|
||||
|
||||
|
@ -7,3 +7,23 @@ pub type FallibleMonad<'a, Ctx, E> = <<Ctx as Context<'a>>::Fallible as MonadFai
|
||||
|
||||
/// Preferred [Wrapped] [Result].
|
||||
pub type FallibleWrapped<'a, Ctx, A, E> = Wrap<'a, A, FallibleMonad<'a, Ctx, E>>;
|
||||
|
||||
/// Extention trait for simpler conversion between [`Context::T`] and [`Context::Fallible`].
|
||||
///
|
||||
/// Until either Rust type system or [`crate::func`] take serious changes,
|
||||
/// this is the preferred way to switch between [Wrapped] and [fallible].
|
||||
pub trait FallibleContext<'a>: Context<'a> {
|
||||
/// Convert a fallible wrapped into a wrapped result.
|
||||
fn unstuff<A: 'a, E: 'a>(
|
||||
wa: WrapE<'a, A, E, Self::Fallible>,
|
||||
) -> Wrap<'a, Result<A, E>, Self::T> {
|
||||
Self::Fallible::unstuff(wa)
|
||||
}
|
||||
|
||||
/// Convert a wrapped result into a fallible wrapped.
|
||||
fn stuff<A: 'a, E: 'a>(fa: Wrap<'a, Result<A, E>, Self::T>) -> WrapE<'a, A, E, Self::Fallible> {
|
||||
Self::Fallible::stuff(fa)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Ctx: Context<'a>> FallibleContext<'a> for Ctx {}
|
||||
|
Loading…
Reference in New Issue
Block a user