BinaryTreesAvl

This commit is contained in:
AF 2023-05-29 23:51:03 +00:00
parent beefedaf2b
commit f5cbf65df9
9 changed files with 551 additions and 43 deletions

View File

@ -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
View 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 }
}
}

View File

@ -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);

View File

@ -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 {}

View File

@ -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 {}

View File

@ -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| {

View 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)),
}
}
}

View File

@ -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::*;

View File

@ -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 {}