Created
September 22, 2009 20:54
-
-
Save eagletmt/191428 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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