use super::{Either, List, Slist, SlistSum, Void};
use core::ops::Add;
pub trait SlistFlatten<T, U>: Slist<T>
where
T: Slist<U>,
{
type Flattened: Slist<U>;
fn flatten(self) -> Self::Flattened;
}
impl<T: Slist<U>, U> SlistFlatten<T, U> for Void {
type Flattened = Void;
#[inline]
fn flatten(self) -> Self::Flattened {
self
}
}
impl<T: Slist<U>, U> SlistFlatten<T, U> for () {
type Flattened = ();
#[inline]
fn flatten(self) -> Self::Flattened {}
}
impl<T, U, N, O> SlistFlatten<T, U> for List<T, N>
where
T: Slist<U>,
N: SlistFlatten<T, U>,
N::Flattened: Add<T, Output = O>,
N::Filter: SlistSum<T, Next = N>,
O: Slist<U>,
{
type Flattened = O;
#[inline]
fn flatten(self) -> Self::Flattened {
self.tail.flatten() + self.head
}
}
impl<T, U, N, M> SlistFlatten<T, U> for Either<N, M>
where
T: Slist<U>,
N: SlistFlatten<T, U>,
M: SlistFlatten<T, U>,
{
type Flattened = Either<N::Flattened, M::Flattened>;
#[inline]
fn flatten(self) -> Self::Flattened {
match self {
Either::Left(n) => Either::Left(n.flatten()),
Either::Right(m) => Either::Right(m.flatten()),
}
}
}