# [−][src]Crate type_freak

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 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, TList, KVList, Counter and Maybe. These types can be initialized by following:

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 a type that implements
Maybe.

use type_freak::maybe::{UnwrapOr, Just, Nothing}; type Outcome1 = UnwrapOr<Just<i8>, u8>; // Outcome1 ~= i8 type Outcome2 = UnwrapOr<Nothing, u8>; // Outcome2 ~= u8

Actually, UnwrapOr is an alias to apply UnwrapOrFunctor on a type. Hence, these statements are equivalent but have longer syntax.

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 and TList allows you to pass a functor for data manipulation. In this example, we pass AddOneFunctor that increases input typed integer by one.

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 also provides LFilter and LScan that acts like Iterator's filter and scan. Their detailed usage is out of scope here.

## Roll your own Functor

You can define your own functor by implementing Functor trait on your type. Here we make a functor that boxes the input type.

use type_freak::functional::Functor; struct BoxFunctor; impl<Input> Functor<Input> for BoxFunctor { type Output = Box<Input>; }

Use ApplyFunctor to apply your functor on a type.

type Out = ApplyFunctor<BoxFunctor, String>; // Out ~= Box<String>

To make sure it works as expected, the crate has a special operator IfSameOutput to let us write static asserttion. If it does its job, the following code should compile without errors.

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 Functors,
while a handful of them are *type operators*. To be exact,

- Functors are structs that implements 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 is a trait that inserts a new type to
TList. LInsertAtOpOutput
is type alias to its `Output`

associated type.
LInsertAtFunctor is the functor wrapping around
above trait, and 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.
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,

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,

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.
These traits are mostly shown in trait bounds.

## Structs as *functors*

A functor is a special struct that implements Functor.
The name ends in `*Functor`

, such as LLengthFunctor.
It works like *type operators*, and it can be applied to Maybe
and 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> type alias to apply a functor on a type. For example,

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.

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> 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>
is alias of `ApplyFunctor<LLengthFunctor, List>`

.

## Modules

boolean | Trait level boolean algebra. |

control | Compile-time guards and static assertions. |

counter | An counter trait that can be automatically inferred, usually used for traversal. |

functional | |

kvlist | A typed list of key-value pairs. |

list | Typed list that supports insertion, removal and look-up. |

maybe | Trait-level equivalences to Option. |

numeric | Numeric type operators and functors. |

tuple | Type operators for tuple types. |

## Macros

KVListType | Builds a type that implements KVList. |

TListType | Builds a type that implements TList. |

TListTypeWithTail | Builds a type that implements TList with extra appending list. |