On Friday, 21 April 2017 at 18:54:38 UTC, David Sanders wrote:
Thank-you for your input. With your help, I was able to figure
out number whether a type is an instantiation of
std.variant.Algebraic.
Now, I need help on concatenating Template Sequence Parameters.
See the block comments below.
Thanks,
Dave
import std.stdio;
import std.variant;
alias Zero = void;
struct One{};
struct Sum(T, U) {
static if (is(T == Zero)) {
static if (is(U == Zero)) {
alias type = Zero;
}
else {
alias type = U;
}
} else static if (is(U == Zero)) {
alias type = T;
} else static if (is(T _ == VariantN!V, V...)) {
static if(is(U _ == VariantN!W, W...)) {
alias type = Algebraic!/* Concatenate V[1..$] with
U[1..$] */
} else {
alias type = Algebraic!/* Concatenate V[1..$] with U */
}
} else static if(is(U _ == VariantN!V, V...)) {
alias type = Algebraic!/* Concatenate T with V[1..$] */
} else {
alias type = Algebraic!(T, U);
}
}
void main() {
static assert (is(Zero == Sum!(Zero, Zero).type));
static assert (is(One == Sum!(Zero, One).type));
static assert (is(One == Sum!(One, Zero).type));
static assert (is(Algebraic!(One, One) == Sum!(One,
One).type));
static assert (is(Algebraic!(One, One, One) == Sum!(Sum!(One,
One).type, One).type));
}
As an aside, there's a less convoluted way to do type-level
arithmetic which is IMO also more concise and looks nicer. You
don't have to mess around with Algebraic at all:
struct Zero;
struct Succ(N);
alias One = Succ!Zero;
alias Pred(N: Zero) = Zero;
alias Pred(N: Succ!Np, Np) = Np;
alias Add(N1: Zero, N2: Zero) = Zero;
alias Add(N1, N2: Zero) = N1;
alias Add(N1: Zero, N2) = N2;
alias Add(N1, N2) = Add!(Succ!N1, Pred!N2);
void main()
{
static assert(is(Pred!One == Zero));
static assert(is(Succ!One == Succ!(Succ!Zero)));
static assert(is(Add!(Zero, Zero) == Zero));
static assert(is(Add!(Zero, One) == One));
static assert(is(Add!(One, Zero) == One));
static assert(is(Add!(One, One) == Succ!(Succ!(Zero))));
alias Two = Succ!One;
static assert(is(Add!(One, One) == Two));
static assert(is(Add!(One, Two) == Succ!(Succ!(Succ!Zero))));
static assert(is(Sub!(Zero, Zero) == Zero));
static assert(is(Sub!(One, Zero) == One));
static assert(is(Sub!(Zero, One) == Zero));
static assert(is(Sub!(Two, One) == One));
static assert(is(Sub!(One, Two) == Zero));
}
Implementing Mul, Div and the integer set is an exercise left to
the reader.