Algebra With Types

Meta via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Fri Apr 21 13:49:27 PDT 2017


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.



More information about the Digitalmars-d-learn mailing list