On Wednesday, 1 April 2015 at 17:51:40 UTC, John Colvin wrote:
Don't really see the point. Here's a neat thing that's
definitely cheating because although it stores the results in
the type system, the arithmetic is done in constant-folding:
struct Integer(int a){}
template Value(T)
{
static if (is(T == Integer!a, int a))
enum Value = a;
else static assert(false, "Can't get Value for " ~
T.stringof);
}
alias Inc(T) = Integer!(Value!T + 1);
But if you really insist on it being all type-system (until you
wan't the answer of course):
struct Zero{}
template Succ(T)
{
static if (is(T == Pred!A, A))
alias Succ = A;
else
struct Succ{}
}
template Pred(T)
{
static if (is(T == Succ!A, A))
alias Pred = A;
else
struct Pred{}
}
enum isPositive(T) = is(T == Succ!A, A);
enum isNegative(T) = is(T == Pred!A, A);
enum isZero(T) = is(T == Zero);
template Add(A, B)
{
static if (isZero!B)
alias Add = A;
else static if (isPositive!B)
alias Add = Add!(Succ!A, Pred!B);
else
alias Add = Add!(Pred!A, Succ!B);
}
template Value(T, int seed = 0)
{
static if (isZero!T)
enum Value = seed;
else static if (isPositive!T)
enum Value = Value!(Pred!T, seed+1);
else
enum Value = Value!(Succ!T, seed-1);
}
unittest
{
alias One = Succ!Zero;
alias Two = Succ!One;
alias MinusThree = Pred!(Pred!(Pred!Zero));
static assert (Value!Zero == 0);
static assert (Value!One == 1);
static assert (Value!Two == 2);
static assert (Value!MinusThree == -3);
static assert (Value!(Add!(One, MinusThree)) == -2);
static assert (Value!(Add!(One, Two)) == 3);
static assert (is(Add!(Add!(One, Two), MinusThree) == Zero));
}
Thanks.