Type Freak

The crate is a collection of typed data structures, trait operators and useful type aliases for Rust. It was introduced to support tch-typed-tensor project, which provides compile-time checked tensor type.

It reduces runtime computation to minimum by design. The DSTs are manipulated by trait operators. That is, with Rust's associated types and generics, we can build non-trivial types like lists and key-value map.

So far, the crate ships following features. It's still in alpha stage and I'm glad for contributions!

Usage

Put this line to your Cargo.toml. Note that the crate is still in alpha stage. Stabilized API is not guaranteed.

toml type-freak = "~0"

Examples

Compile-time guards and static assertions

To assert one typed integer is less than the other typed integer:

```rust use typenum::consts::*; use type_freak::control::IfLessOutput;

type Out1 = IfLessOutput; // U3 < U5 is true, thus Out1 ~= usize type Out2 = IfLessOutput; // U5 < U5 is false

fn assert() { let _: Out1 = 0; // Goes fine here. let _: Out2 = 0; // Compile error!!! } ```

We can make sure two generic parameters are of the same type by IfSame trait bound.

```rust use type_freak::control::IfSame;

fn guardedfunction() -> String where Lhs: IfSame { "Yeeeeeee!".toowned() }

fn comileme() { let _ = guardedfunction::(); // fine let _ = guarded_function::(); // Compile error!!! } ```

Typed list

The TList type represents a list of arbitrary types. It can be constructed by TListType! macro. The crate ships a variety of traits as type operators to manipuate the list structure.

```rust use type_freak::{TListType, list::*};

type List1 = TListType![u8, u16, u32];

type List2 = LPrepend; // List2 ~= TListType![u64, u8, u16, u32]

type List3 = LRemoveAt; // List3<_> ~= TListType![u64, u8, u32]

type List4 = LAppend, f32>; // List4 ~= TListType![u64, u8, u32, f32]

type List5 = LInsertAt, u8, f64, Index2>; // List5 ~= TListType![u64, u8, f64, u32, f32] ```

Functional interface

You can map, filter or scan a TList with existing functors in crate. Also, it's allowed to roll your own functor to manipulate the data with ease.

```rust struct BoxFunctor;

impl Functor for BoxFunctor { type Output = Box; }

type ListBefore = TListType![String, [i64; 7], isize, (), (f64, f32)]; type ListAfter = LMap;

type Assert = IfSameOutput< (), ListAfter, TListType! { Box, Box<[i64; 7]>, Box, Box<()>, Box<(f64, f32)> },

;

fn assert() { let _: Assert = (); // static assertion } ```

Trait-level Option

The Maybe is analogous to std's Option.

```rust use typenum::consts::*; use type_freak::maybe::{Maybe, Just, Nothing};

type Opt1 = Just; type Opt2 = Nothing;

type Val1 = Unwrap; // U3 type Val2 = UnwrapOr; // U3 type Val3 = UnwrapOr; // U0 ```

Auto-inferred counters

The Counter traits along with Next and Current types are handly tools to build recursive type operators. The following demo implements an trait that removes a specific type from TList.

The example works by a termination step and recursive step, corresponding to to impl blocks. Note that the Index argument is necessary to let compiler distinguish the signatures of two impl blocks. Otherwise, the compiler will complain about conflicting implementations.

```rust use type_freak::{ list::{TList, LCons, LNil}, counter::{Counter, Current, Next}, };

/* Definition */

pub trait LRemoveAt where Index: Counter, Self: TList, Self::Output: TList, { type Output; }

// termination step impl LRemoveAt for LCons where Tail: TList, { type Output = Tail; }

// recursion step impl LRemoveAt> for LCons where Index: Counter, Tail: TList + LRemoveAt, { type Output = LCons>::Output>; }

/* Auto-inference example */

// Here SomeList is equivalent to TListType![u8, u32] type SomeList = >::Output;

// The Index argument can be inferred by compiler fn auto_inference() { let _ = SomeList::<_>::new(); } ```

License

The project licensed under MIT or Apache 2.0. Pick the one that suits you.