Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add examples to readme #210

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 81 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,92 @@ type Y = Exp<N2, P3>;
assert_eq!(<Y as Integer>::to_i32(), -8);
```

For a non-trivial example of its use, see one of the crates that depends on
it. The full list is
[here](https://crates.io/crates/typenum/reverse_dependencies). Of note are

And how to use constraints:

```rust
use typenum::{self, IsGreater, True, U0};
trait NonZero {
type NonZero: IsGreater<U0, Output = True>;
}
```
<details>

<summary>Unfold here to see a (somwhat contrived) exploitation of type-level integer arithmetic:</summary>

```rust
// Imports to make rust playground happy
use core::ops::{Div, Add, Mul};
use typenum::{op, *};
use generic_array::{GenericArray, ArrayLength};

// Demo-time. A simple "flatten a 2d bool-array to a 1d byte-array"
// Let's encapsulate a 2d array, similar to `[[bool; WIDTH]; HEIGHT]`
pub struct FlattenDemo<
Width: ArrayLength,
Height: ArrayLength,
> {
unflattened: GenericArray<GenericArray<bool, Width >, Height>,
}

// For fun and profit, let's wrap-up the behavior in a trait.
trait Flatten {
// NOTE: the `generic-array` crate is pretty cool.
type FlattenedLen: ArrayLength;
fn flattened(self) -> GenericArray<bool, Self::FlattenedLen>;
}


// So here is the fun part: Flattening using compile-time maths, but using the type-system.
// Flattening into a byte-array, you must ensure a multiple of 8, to Illustrate:
// A: 2 x 3 = 6. so need a 1-byte array
// B: 2 x 4 = 8: 8 is the nearest round-up, again; 1-byte array
// C: 3 x 7 = 21: need to round up to 24: 3-byte array
//
// This is done by taking the needed bits, adding 7, then integer-division to 8
// A: (6 + 7) / 8 = 13 / 8 = 1
// B: (8 + 7) / 8 = 15 / 8 = 1
// A: (21 + 7) / 8 = 28 / 8 = 3
impl<Width: ArrayLength, Height: ArrayLength> Flatten for FlattenDemo<Width, Height>
where
// Types are not values: Unlike integer values, all of which implement the behavior of
// integers (multiplication, addition, division, etc) as an inherent part of the language,
// the compiler has no way of knowing if a given type implements a given operation unless
// you explicitly specify...
//
// 1. We must specify that the `Width` type must implement behavior in which it `Mul`tiplies
// the `Height` type:
Width: Mul<Height>,
// 2. We also must specify that this `Mul`tiply behaviors `Output` implements the
// "`Add`ition on `U7`" behavior:
op!(Width * Height): Add<U7>,
// 3. And so on: This is the constraint "The result of (width * height) + 7 must implement
// division by 8", but without the `op!` convenience macro:
<<Width as Mul<Height>>::Output as Add<U7>>::Output: Div<U8>,
// With the convenience macro:
// op!((Width * Height) + U7): Div<U8>,
op!((Width * Height + U7) / U8): ArrayLength,

{
// Et, voila! Through the power of the type system, we have lifted arithmetic to compile
// time, without the use of nightly, the need to think about machine-representation of
// values (usize/u64/etc).
type FlattenedLen = op!((Width * Height + U7) / U8);
fn flattened(self) -> GenericArray<bool, Self::FlattenedLen> {
todo!()
}
}
```
</details>

For more non-trivial examples, with real-world use, check the full list of
reverse dependencies [here](https://crates.io/crates/typenum/reverse_dependencies). Of note are
[dimensioned](https://crates.io/crates/dimensioned/) which does compile-time
type checking for arbitrary unit systems and
[generic-array](https://crates.io/crates/generic-array/) which provides arrays
whose length you can generically refer to.


### Error messages


Expand Down