1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//! Typed list that supports insertion, removal and look-up.
//!
//! ## Type construction
//! The [TList](crate::list::TList) trait represents a typed list of arbitrary types.
//! The type [LCons](crate::list::LCons) forms intermediate nodes, while
//! [LNil](crate::list::LNil) type marks the end of list. For a list of `u8`, `u16`
//! and `u32` types:
//!
//! ```ignore
//! LCons<u8, LCons<u16, LCons<u32, LNil>>>
//! ```
//!
//! Most of the time you don't need to write in this cumbersome way.
//! The [TListType] macro let you write in more compact syntax. For example,
//!
//! ```ignore
//! TListType![u8, u16, u32]
//! ```
//!
//! ## List manipuation
//! The module ships a collection of _type operators_ to manipulate lists,
//! including [LPrepend](crate::list::LPrepend), [LAppend](crate::list::LAppend),
//! [LInsertAt](crate::list::LInsertAt), [LRemoveAt](crate::list::LRemoveAt).
//! As the name explains itself, you can append or prepend a type to this list,
//! insert a new type after a some type, or remove a specific type. We can work
//! it out by their type aliases for convenience.
//!
//! ```rust
//! use type_freak::{TListType, list::*};
//!
//! type List1 = TListType![u8, u16, u32];
//!
//! type List2 = LPrepend<List1, u64>;
//! // List2 ~= TListType![u64, u8, u16, u32]
//! // is alias of <List1 as LPrepend<List1, u64>>::Output
//!
//! type List3<Index1> = LRemoveAt<List2, u16, Index1>;
//! // List3<_> ~= TListType![u64, u8, u32]
//!
//! type List4<Index1> = LAppend<List3<Index1>, f32>;
//! // List4 ~= TListType![u64, u8, u32, f32]
//!
//! type List5<Index1, Index2> = LInsertAt<List4<Index1>, u8, f64, Index2>;
//! // List5 ~= TListType![u64, u8, f64, u32, f32]
//! ```
//!
//! As shown in the example, [LInsertAt](crate::list::LInsertAt),
//! [LRemoveAt](crate::list::LRemoveAt) along with other type operators
//! have a special `Index` generic type argument. It is necessary for
//! list traversal. Most of the time we can leave it undetermined.
//! It can be inferred by compiler when constructing concrete type.
//!
//! ```ignore
//! let _ = List5::<_, _>::new();
//! ```
//!
//! ## Marker traits
//! The [EmptyTList](crate::list::marker::EmptyTList) and [NonEmptyTList](crate::list::marker::NonEmptyTList)
//! traits can be used in trait bounds. Suppose you wish to accept a non-empty
//! [TList](crate::list::TList) type:
//!
//! ```ignore
//! trait ExampleTrait<List: NonEmptytList> { /* ... */ }
//! ```
//! ## Numeric type operators
//! [LReduceMax](crate::list::LReduceMax), [LReduceMin](crate::list::LReduceMin),
//! [LReduceSum](crate::list::LReduceSum) and [LReduceProd](crate::list::LReduceProd)
//! assume all contained types are [typenum] typed numbers. You may `use typenum::consts::*`
//! to work with [typenum] constants.
//!
//! ```rust
//! use type_freak::{TListType, list::LReduceSum};
//! use typenum::consts::*;
//!
//! type Value = LReduceSum<TListType![P3, N5, Z0]>;  // Value ~= P2
//! ```
//!
//! The [LToUsizeVec](crate::list::LToUsizeVec) provides a
//! [to_usize_vec](crate::list::LToUsizeVec::to_usize_vec) to build concrete
//! `Vec<usize>` type.
//!
//! ```ignore
//! // Gets vec![3, -5, 0]
//! let values = <TListType![P3, N5, Z0] as LToUsizeVec>::to_usize_vec();
//! ```

mod functional;
mod indexing;
mod insert;
mod macros;
pub mod marker;
mod misc;
mod reduction;
mod remove;
mod zipping;

pub use functional::*;
pub use indexing::*;
pub use insert::*;
pub use macros::*;
pub use misc::*;
pub use reduction::*;
pub use remove::*;
pub use zipping::*;

use std::marker::PhantomData;

// list

/// Represents a typed list constructed by [LCons] and [LNil].
pub trait TList {}

// intermediate node

/// Represents an intermediate node.
pub struct LCons<Head, Tail>
where
    Tail: TList,
{
    _phantom: PhantomData<(Head, Tail)>,
}

impl<Head, Tail> LCons<Head, Tail>
where
    Tail: TList,
{
    pub fn new() -> LCons<Head, Tail> {
        Self {
            _phantom: PhantomData,
        }
    }
}

impl<Head, Tail> TList for LCons<Head, Tail> where Tail: TList {}

// end of list

/// Represents the end of list.
pub struct LNil;

impl TList for LNil {}