Skip to content

Instantly share code, notes, and snippets.

@eagletmt
Created September 22, 2009 20:54
Show Gist options
  • Save eagletmt/191428 to your computer and use it in GitHub Desktop.
Save eagletmt/191428 to your computer and use it in GitHub Desktop.
class Nil {}
class Cons(X, XS) {}
template length(T) {
static if (is(T == Nil)) {
const length = 0;
} else static if (is(T _ == Cons!(X, XS), X, XS)) {
const length = 1 + length!(XS);
}
}
template head(T) {
static if (is(T _ == Cons!(X, XS), X, XS)) {
alias X head;
}
}
template tail(T) {
static if (is(T _ == Cons!(X, XS), X, XS)) {
alias XS tail;
}
}
template drop(int n, T) {
static if (n == 0) {
alias T drop;
} else static if (is(T _ == Cons!(X,XS), X, XS)) {
alias drop!(n-1, XS) drop;
}
}
template take(int n, T) {
static if (n == 0) {
alias Nil take;
} else static if (is(T _ == Cons!(X,XS), X, XS)) {
alias Cons!(X, take!(n-1, XS)) take;
}
}
template append(T, U) {
static if (is(T == Nil)) {
alias U append;
} else static if (is(T _ == Cons!(X, XS), X, XS)) {
alias Cons!(X, append!(XS, U)) append;
}
}
template reverse_(U, V) {
static if (is(U == Nil)) {
alias V reverse_;
} else static if (is(U _ == Cons!(X, XS), X, XS)) {
alias reverse_!(XS, Cons!(X, V)) reverse_;
}
}
template reverse(T) {
alias reverse_!(T, Nil) reverse;
}
template map(alias F, T) {
static if (is(T == Nil)) {
alias Nil map;
} else static if (is(T _ == Cons!(X, XS), X, XS)) {
alias Cons!(F!(X), map!(F, XS)) map;
}
}
template filter(alias P, T) {
static if (is(T == Nil)) {
alias Nil filter;
} else static if (is(T _ == Cons!(X, XS), X, XS)) {
static if (P!(X)) {
alias Cons!(X, filter!(P, XS)) filter;
} else {
alias filter!(P, XS) filter;
}
}
}
template to_pointer(T) {
alias T* to_pointer;
}
template is_arithmetic(T) {
const is_arithmetic = __traits(isArithmetic, T);
}
class Zero {}
class Succ(Z) {}
template add(T, U) {
static if (is(T == Zero)) {
alias U add;
} else static if (is(T _ == Succ!(V), V)) {
alias Succ!(add!(V, U)) add;
}
}
void main()
{
alias Cons!(int, Cons!(real, Cons!(string, Nil))) as;
static assert(length!(as) == 3);
static assert(is(head!(as) == int));
static assert(is(tail!(as) == Cons!(real, Cons!(string, Nil))));
static assert(is(drop!(1, as) == Cons!(real, Cons!(string, Nil))));
static assert(is(take!(1, as) == Cons!(int, Nil)));
static assert(is(append!(drop!(1, as), take!(1, as)) == Cons!(real, Cons!(string, Cons!(int, Nil)))));
static assert(is(reverse!(as) == Cons!(string, Cons!(real, Cons!(int, Nil)))));
static assert(is(map!(to_pointer, as) == Cons!(int*, Cons!(real*, Cons!(string*, Nil)))));
static assert(is(filter!(is_arithmetic, as) == Cons!(int, Cons!(real, Nil))));
alias Succ!(Zero) one;
alias Succ!(Succ!(Zero)) two;
alias add!(one, two) three;
static assert(is(three == Succ!(Succ!(Succ!(Zero)))));
static assert(is(add!(two, three) == Succ!(Succ!(Succ!(Succ!(Succ!(Zero)))))));
alias Cons!(one, Cons!(Zero, Nil)) xs;
static assert(is(map!(Succ, xs) == Cons!(two, Cons!(one, Nil))));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment