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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
//! This crate provides collections of runtime-free, type-level data structures
//! and type operators.
//!
//! The design of this crate promises these properties:
//! - **Runtime-free**: Most type operations are done in compile-time.
//! - **No concrete data**: Structs and enums contain at most
//!                         [PhantomData](std::marker::PhantomData) fields.
//! - **Less writing**: It tries to make use of type aliases to save some inks.
//!
//! # Basics
//! This crate provides type-level data structures categorized by traits, including
//! [Boolean](crate::boolean::Boolean), [TList](crate::list::TList),
//! [KVList](crate::kvlist::KVList), [Counter](crate::counter::Counter) and
//! [Maybe](crate::maybe::Maybe).
//! These types can be initialized by following:
//!
//! ```rust
//! use type_freak::{
//!     TListType,
//!     KVListType,
//!     list::{LCons, LNil},
//!     counter::{Current, Next},
//!     maybe::{UnwrapOr, Just, Nothing},
//! };
//! use typenum::{True, False, consts::*};
//!
//! type List1 = TListType![String, Option<i8>];         // impl TList trait
//! type List2 = LCons<String, LCons<Option<i8>, LNil>>;  // same as above
//! type MaybeJust = Just<f32>;                           // impl Maybe
//! type MaybeNothing = Nothing;                          // impl Maybe
//! type BoolTrue = True;                                 // impl Boolean
//! type BoolFalse = False;                               // impl Boolean
//! type Kv = KVListType![(isize, U0), (usize, U1)];     // impl KVList
//! type Cnt = Next<Next<Next<Current>>>;                 // impl Counter
//! ```
//!
//! Each data structure is manipuated either by _functors_
//! or _type operators_. The distinction is due to implementation contraints, and it
//! is encourage to use functors at first.
//! For example, you can [UnwrapOr](crate::maybe::UnwrapOr) a type that implements
//! [Maybe](crate::maybe::Maybe).
//!
//! ```rust
//! use type_freak::maybe::{UnwrapOr, Just, Nothing};
//! type Outcome1 = UnwrapOr<Just<i8>, u8>;  // Outcome1 ~= i8
//! type Outcome2 = UnwrapOr<Nothing, u8>;   // Outcome2 ~= u8
//! ```
//!
//! Actually, [UnwrapOr](crate::maybe::UnwrapOr) is an alias to apply
//! [UnwrapOrFunctor](crate::maybe::UnwrapOrFunctor) on a type. Hence, these statements
//! are equivalent but have longer syntax.
//!
//! ```rust
//! use type_freak::{
//!     maybe::{UnwrapOrFunctor, Just, Nothing},
//!     functional::ApplyFunctor,
//! };
//! type Outcome1 = ApplyFunctor<UnwrapOrFunctor<u8>, Just<i8>>;  // Outcome1 ~= i8
//! type Outcome2 = ApplyFunctor<UnwrapOrFunctor<u8>, Nothing>;   // Outcome1 ~= u8
//! ```
//!
//! # Functoinal interface
//! ## Usage
//! Both [Maybe](crate::maybe::Maybe) and [TList](crate::list::TList) allows you to
//! pass a functor for data manipulation. In this example, we pass
//! [AddOneFunctor](crate::numeric::AddOneFunctor) that increases input typed integer
//! by one.
//!
//! ```rust
//! use type_freak::{
//!     TListType,
//!     list::LMap,
//!     maybe::{Just, Nothing},
//!     numeric::AddOneFunctor,
//! };
//! use typenum::consts::*;
//!
//! type Out1 = LMap<TListType![U3, U2, U5], AddOneFunctor>;
//! // Out1 ~= TListType![U4. U3. U5]
//!
//! type Out2 = LMap<Just<U7>, AddOneFunctor>;
//! // Out2 ~= Just<U8>
//!
//! type Out3 = LMap<Nothing, AddOneFunctor>;
//! // Out3 ~= Nothing
//! ```
//!
//! [TList](crate::list::TList) also provides [LFilter](crate::list::LFilter) and
//! [LScan](crate::list::LScan) that acts like [Iterator](std::iter::Iterator)'s
//! [filter](std::iter::Iterator::filter) and [scan](std::iter::Iterator::scan).
//! Their detailed usage is out of scope here.
//!
//! ## Roll your own [Functor](crate::functional::Functor)
//! You can define your own functor by implementing [Functor](crate::functional::Functor)
//! trait on your type. Here we make a functor that boxes the input type.
//!
//! ```rust
//! use type_freak::functional::Functor;
//! struct BoxFunctor;
//!
//! impl<Input> Functor<Input> for BoxFunctor {
//!     type Output = Box<Input>;
//! }
//!
//! ```
//!
//! Use [ApplyFunctor](crate::functional::ApplyFunctor) to apply your functor on a type.
//!
//! ```ignore
//! type Out = ApplyFunctor<BoxFunctor, String>;  // Out ~= Box<String>
//! ```
//!
//! To make sure it works as expected, the crate has a special operator
//! [IfSameOutput](crate::control::IfSameOutput) to let us write static asserttion.
//! If it does its job, the following code should compile without errors.
//!
//! ```rust
//! use type_freak::{
//!     functional::{Functor, ApplyFunctor},
//!     control::IfSameOutput
//! };
//!
//! struct BoxFunctor;
//!
//! impl<Input> Functor<Input> for BoxFunctor {
//!     type Output = Box<Input>;
//! }
//!
//! type Out = ApplyFunctor<BoxFunctor, String>;  // Out ~= Box<String>
//! type Assert = IfSameOutput<(), Out, Box<String>>;
//!
//! fn assert() {
//!     let _: Assert = ();
//! }
//!
//! ```
//!
//! # Functors vs type operators
//! Most operations in this crate are in by [Functor](crate::functional::Functor)s,
//! while a handful of them are _type operators_. To be exact,
//!
//! - Functors are structs that implements [Functor](crate::functional::Functor) trait.
//! - Type operators are traits that has `Output` associated type.
//!
//! They serves for the same purpose. Since recursive associated types only works on
//! trait type operators, some of the operators have both a trait and a functor.
//!
//! For example,
//! [LInsertAtOp](crate::list::LInsertAtOp) is a trait that inserts a new type to
//! [TList](crate::list::TList). [LInsertAtOpOutput](crate::list::LInsertAtOpOutput)
//! is type alias to its `Output` associated type.
//! [LInsertAtFunctor](crate::list::LInsertAtFunctor) is the functor wrapping around
//! above trait, and [LInsertAt](crate::list::LInsertAt) is an alias to apply the functor.
//!
//! # Naming conventions
//! Each traits, structs and type aliases serves their own purpose. The naming of
//! these primitives tell you the usage and how the outcome could be.
//!
//! ## Traits as _type operators_
//! The name has pattern `*Op`, such as [FirstOfOp](crate::list::LLengthOp).
//! Most _type operators_ have a `Output` associated type to represent the outcome
//! of type transformation. You can obtain the outcome by trait casting. For example,
//!
//! ```ignore
//! type Outcome = <TListType![i8, i16] as LLengthOp<>>::Output;  // Outcome ~= U2
//! ```
//!
//! Due to the cumbersome syntax, most type operators have a corresponding type
//! alias to capture the output. For example,
//!
//! ```ignore
//! type Outcome = LLengthOpOutput<TListType![i8, i16]>;  // Output ~= U2
//! ```
//!
//! ## Traits as _markers_
//! Marker traits are usually placed under `marker` namespace. For example,
//! [type_freak::list::marker::EmptyTList](crate::list::marker::EmptyTList).
//! These traits are mostly shown in trait bounds.
//!
//! ## Structs as _functors_
//! A functor is a special struct that implements [Functor](crate::functional::Functor).
//! The name ends in `*Functor`, such as [LLengthFunctor](crate::list::LLengthFunctor).
//! It works like _type operators_, and it can be applied to [Maybe](crate::maybe::Maybe)
//! and [TList](crate::list::TList). Most type operations have a functor interface,
//! either by wrapping around a _type operator_ trait or by standalone definition.
//!
//! The crate provides [ApplyFunctor\<Func, Input\>](crate::functional::ApplyFunctor)
//! type alias to apply a functor on a type. For example,
//!
//! ```ignore
//! type Outcome = ApplyFunctor<LLengthFunctor, TListType![u8, u16]>;  // Outcome ~= U2
//! // Same as `LLengthFunctor as Functor<TListType![u8, u16]>`
//! ```
//!
//! Also, type aliases are available to save the pen and ink.
//!
//! ```ignore
//! type Outcome = LLength<TListType![u8, u16]>;  // Outcome ~= U2
//! ```
//!
//! ## Type aliases as _type operator aliases_
//!
//! Most alias names ends in `*OpOutput`. For example, the name
//! [LLengthOpOutput\<List\>](crate::list::LLengthOpOutput) is the alias of
//! `<List as LLengthOp>::Output`.
//!
//! ## Type aliases as _functor aliases_
//! It is a short hand syntax to apply a functor on a type. The name has no
//! special suffix. For example, [LLength\<List\>](crate::list::LLength)
//! is alias of `ApplyFunctor<LLengthFunctor, List>`.
//!
//!
//!

#![feature(vec_remove_item)]

pub mod boolean;
pub mod control;
pub mod counter;
pub mod functional;
pub mod kvlist;
pub mod list;
pub mod maybe;
pub mod numeric;
pub mod tuple;