use core::fmt;
use std::any::type_name;
use std::fmt::Debug;
use std::marker::PhantomData;
pub mod ops;
#[cfg(test)]
pub(crate) mod test_types;
pub mod traits;
pub mod types;
pub trait ConsCell: Sized {
fn extend<NewHead>(self, new_head: NewHead) -> <Self as Extend<NewHead>>::Extension
where
Self: Extend<NewHead>,
{
Self::Extension::new(new_head, self)
}
}
pub trait Extend<NewHead> {
type Extension: Cons<Head = NewHead, Tail = Self>;
}
pub trait NilExtend<NewHead>: Sized {
type Extension: Cons<Head = NewHead, Tail = Nil<Self>>;
}
pub struct Nil<NilSeed> {
_marker: PhantomData<NilSeed>,
}
impl<NilSeed> Nil<NilSeed> {
pub fn new() -> Self {
Nil {
_marker: Default::default(),
}
}
}
impl<NilSeed> ConsCell for Nil<NilSeed> {}
impl<NewHead, NilSeed> Extend<NewHead> for Nil<NilSeed>
where
NilSeed: NilExtend<NewHead>,
{
type Extension = <NilSeed as NilExtend<NewHead>>::Extension;
}
impl<NilSeed> Debug for Nil<NilSeed> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct(type_name::<NilSeed>()).finish()
}
}
pub trait Cons: ConsCell {
type Head;
type Tail: ConsCell;
fn head(&self) -> &Self::Head;
fn tail(&self) -> &Self::Tail;
fn mut_head(&mut self) -> &mut Self::Head;
fn mut_tail(&mut self) -> &mut Self::Tail;
fn new(head: Self::Head, tail: Self::Tail) -> Self;
fn split(self) -> (Self::Head, Self::Tail);
}