#![feature(tuple_trait, import_trait_associated_functions, never_type)] #![no_std] #![allow(mixed_script_confusables, confusable_idents)] //! ![view](https://raw.githubusercontent.com/learnyouahaskell/learnyouahaskell.github.io/e4282695721ed62b746d213aa81265f8c254fbf2/static/assets/images/starting-out/listmonster.png) //! //! start with [`Tupl`]. mod implementations; mod iterator; mod picks; pub use iterator::IteratorOfTuples; /// Reverse a tuple. pub trait Reverse: Tupl { type Reversed: Tupl; fn reverse(self) -> Self::Reversed; } #[doc(inline)] pub use Reverse::{reverse, reverse as flip}; #[doc(inline)] pub use Tupl::{ drop, head, head as left, head as fst, last, last as right, pick, take, }; pub use picks::*; /// Construct a tuple. pub fn cons>(x: T, y: Tup) -> Tup::Cons { Tup::Cons::cons(x, y) } /// Construct a tuple, backwards. pub fn snoc>(x: Tup, y: T) -> Tup::Snoc { Tup::Snoc::snoc(x, y) } /// alias for [`snoc`] pub trait Push: Tupl { type Result; /// ``` /// use ttools::*; /// let x = (1, 2).push(3); /// assert_eq!(x, ((1, 2, 3))); /// ``` fn push(self, other: T) -> Self::Result; } /// alias for [`cons`] pub trait With { type Result; /// ``` /// use ttools::*; /// let x = 1.with((2, 3)); /// assert_eq!(x, ((1, 2, 3))); /// ``` fn with(self, other: T) -> Self::Result; } // implemented for the constructed type pub trait Cons: Tupl { /// (T, ..self) type Cons: Tupl; /// (..self, T) type Snoc: Tupl; } /// backing trait for [`take`]. pub trait TD: Tupl { /// self[N..] type Drop: Tupl; /// self[..N] type Take: Tupl; // self[LEN - N..] type TakeB: Tupl; /// self[..LEN - N] type DropB: Tupl; /// deconstruct fn dropf(self) -> (Self::Take, Self::Drop); /// deconstruct fn dropb(self) -> (Self::DropB, Self::TakeB); } /// backing trait for [`pick`] pub trait Pick: Tupl { /// `self[N]` type At; /// self[..N] type L: Tupl; /// self[N + 1..] type R: Tupl; /// self::L + Self::R type Delete: Tupl; /// without Self::At fn delete(l: Self::L, r: Self::R) -> Self::Delete; /// reconstruct fn repick(l: Self::L, at: Self::At, r: Self::R) -> Self; /// deconstruct fn depict(self) -> (Self::L, Self::At, Self::R); } pub trait RePick: Pick + Sized { type New: Tupl; fn unpick(l: Self::L, at: T, r: Self::R) -> Self::New; } /// Main tuple trait. #[diagnostic::on_unimplemented( label = "this is not a tuple, or it is too big a tuple (>26 elements)" )] pub trait Tupl: core::marker::Tuple { /// Refer to listmonster. type Head; /// Refer to listmonster. type Last; /// Refer to listmonster. type Tail: Tupl; /// Refer to listmonster. type Init: Tupl; /// Middle section of listmonster. type Inner: Tupl; /// Size of tuple. const LEN: usize; /// Note: Partial function. #[doc(alias = "left")] fn head(self) -> Self::Head where Self: Sized, { self.uncons().0 } /// Note: Partial function. #[doc(alias = "right")] fn last(self) -> Self::Last where Self: Sized, { self.unsnoc().1 } /// Note: Partial function. fn take(self) -> Self::Take where Self: TD + Sized, { self.dropf().0 } /// Note: Partial function. fn drop(self) -> Self::Drop where Self: TD + Sized, { self.dropf().1 } /// Note: Partial function. fn take_back(self) -> Self::TakeB where Self: TD + Sized, { self.dropb().1 } /// Note: Partial function. fn drop_back(self) -> Self::DropB where Self: TD + Sized, { self.dropb().0 } /// Gives you the element at index N (from 0). /// Note: partial function fn pick(self) -> Self::At where Self: Pick + Sized, { self.depict().1 } /// unconstructs self, returning head and tail (see listmonster) fn uncons(self) -> (Self::Head, Self::Tail); /// untcurtsnocs self, returning init and last (see listmonster) fn unsnoc(self) -> (Self::Init, Self::Last); /// weird thing, full construct fn fcons( start: Self::Head, inner: Self::Inner, last: Self::Last, ) -> Self; /// reconstruct; dont use directly fn cons(head: Self::Head, tail: Self::Tail) -> Self; /// retcurtsnoc; dont use directly fn snoc(init: Self::Init, last: Self::Last) -> Self; } #[test] fn t() { 2.with(cons(4i8, (1i16, 2i32)).push(2)) .take::<2>() .push(4) .push(0u8) .pick::<3>(); }