TypeNum 0.3.0
dotnet add package TypeNum --version 0.3.0
NuGet\Install-Package TypeNum -Version 0.3.0
<PackageReference Include="TypeNum" Version="0.3.0" />
paket add TypeNum --version 0.3.0
#r "nuget: TypeNum, 0.3.0"
// Install TypeNum as a Cake Addin #addin nuget:?package=TypeNum&version=0.3.0 // Install TypeNum as a Cake Tool #tool nuget:?package=TypeNum&version=0.3.0
TypeNum
Type-level integers for C#
Example
class Tensor<NCols, NRows>
where NCols : struct, INumeral
where NRows : struct, INumeral
{
public static int ColumnCount { get; } = NCols.Num;
public static int RowCount { get; } = NRows.Num;
internal readonly float[,] values = new float[ColumnCount, RowCount];
public void Add(Tensor<NCols, NRows> tensor)
{
for (int col = 0; col < ColumnCount; col++)
for (int row = 0; row < RowCount; row++)
this.values[col, row] += tensor.values[col, row];
}
}
Shorthands
For non-power-of-two numerals it is useful to add shorthands. Unfortunately declaring one is rather verbose in C#:
using N39 = TypeNum.Sum<TypeNum.Sum<TypeNum.Sum<
TypeNum.N32,
TypeNum.N4>,
TypeNum.N2>,
TypeNum.N1>;
...
Debug.Assert(N39.Num == 39);
var thirtyNine = new Tensor<N39, N39>();
Consistency
Technically, Sum<N1, N0>
and Sum<N0, N1>
represent the same numeral.
However, there is no way to express it in C# type system. To alleviate that
TypeNum tries to enforce one and only way to represent specific number.
To take advantage of that enforcement, avoid declaring your own implementations
of the Numeral
interface, and stick to N*
, Twice<T>
, and Sum<T1, T2>
classes. They enforce several rules at run time (and, potentially, compile
time in the future):
Twice
In Twice<T>
T
can only be one of the following:
- the largest predefined type numeral (currently
N4096
) - another
Twice<*>
So Twice<T>
can only be used to represent very large numerals
Sum
The following rules are enforced on parameters T1
and T2
of Sum<T1, T2>
:
T1.Num
must be strictly greater (>) thanT2.Num
(swap them, if yours are opposite)T2
can never be anotherSum<*,*>
. Replace anySum<A, Sum<B, C>>
withSum<Sum<A, B>, C>
- if
T1
itself is aSum<A, B>
, then inSum<Sum<A, B>, C>
A
andB
must each be strictly greater (>) thanC
Following these rules will ensure, that equal type numerals are always represented by identical types.
F# Example
In F# (unlike C#) operators can introduce new generic type parameters, which enables defining statically-typed matrix multiplication as an operator:
type Matrix<'rows, 'cols>() =
static member ( * )(left: Matrix<'rows, 'cols>, right: Matrix<'cols, 'ncols>) =
Matrix<'rows, 'ncols>()
module private Test =
open TypeNum
type N3 = Sum<N2, N1>
type N7 = Sum<N4, N3>
type N5 = Sum<N4, N1>
let a = Matrix<N7, N5>()
let b = Matrix<N5, N3>()
let product = a * b
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net7.0
- System.Memory (>= 4.5.5)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on TypeNum:
Package | Downloads |
---|---|
Small
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
0.3.0 | 241 | 2/16/2023 |
0.2.0 | 117 | 1/13/2024 |
0.2.0-CI-20210909-064812 | 248 | 9/9/2021 |
0.1.0-CI-20200206-090900 | 379 | 2/6/2020 |