Skip to content

Instantly share code, notes, and snippets.

@io12
Created July 27, 2020 23:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save io12/ce6d2e9075bbbb7c294af5b58dd582ba to your computer and use it in GitHub Desktop.
Save io12/ce6d2e9075bbbb7c294af5b58dd582ba to your computer and use it in GitHub Desktop.
struct Cons<HEAD, TAIL>(HEAD, TAIL);
struct Nil;
struct Z;
struct S<N>(N);
struct True;
struct False;
struct Fizz;
struct Buzz;
struct FizzBuzz;
type N1 = S<Z>;
type N2 = S<N1>;
type N3 = S<N2>;
type N4 = S<N3>;
type N5 = S<N4>;
type N6 = S<N5>;
type N7 = S<N6>;
type N8 = S<N7>;
type N9 = S<N8>;
type N10 = S<N9>;
type N50 = Add<N10, Add<N10, Add<N10, Add<N10, N10>>>>;
type N100 = Add<N50, N50>;
type Add<A, B> = <A as AddT<B>>::Out;
trait AddT<A> {
type Out;
}
impl<A> AddT<A> for Z {
type Out = A;
}
impl<A, B> AddT<A> for S<B>
where
B: AddT<S<A>>,
{
type Out = <B as AddT<S<A>>>::Out;
}
type And<A, B> = <A as AndT<B>>::Out;
trait AndT<A> {
type Out;
}
impl AndT<False> for False {
type Out = False;
}
impl AndT<True> for False {
type Out = False;
}
impl AndT<False> for True {
type Out = False;
}
impl AndT<True> for True {
type Out = True;
}
type Append<ITEM, LIST> = <LIST as AppendT<ITEM>>::Out;
trait AppendT<ITEM> {
type Out;
}
impl<ITEM> AppendT<ITEM> for Nil {
type Out = Cons<ITEM, Nil>;
}
impl<ITEM, HEAD, TAIL> AppendT<ITEM> for Cons<HEAD, TAIL>
where
TAIL: AppendT<ITEM>,
{
type Out = Cons<HEAD, Append<ITEM, TAIL>>;
}
type DivisibleBy3<N> = <N as DivisibleBy3T>::Out;
trait DivisibleBy3T {
type Out;
}
impl DivisibleBy3T for Z {
type Out = True;
}
impl DivisibleBy3T for N1 {
type Out = False;
}
impl DivisibleBy3T for N2 {
type Out = False;
}
impl<N> DivisibleBy3T for S<S<S<N>>>
where
N: DivisibleBy3T,
{
type Out = DivisibleBy3<N>;
}
type DivisibleBy5<N> = <N as DivisibleBy5T>::Out;
trait DivisibleBy5T {
type Out;
}
impl DivisibleBy5T for Z {
type Out = True;
}
impl DivisibleBy5T for N1 {
type Out = False;
}
impl DivisibleBy5T for N2 {
type Out = False;
}
impl DivisibleBy5T for N3 {
type Out = False;
}
impl DivisibleBy5T for N4 {
type Out = False;
}
impl<N> DivisibleBy5T for S<S<S<S<S<N>>>>>
where
N: DivisibleBy5T,
{
type Out = DivisibleBy5<N>;
}
type If<COND, THEN, ELSE> = <COND as IfT<THEN, ELSE>>::Out;
trait IfT<THEN, ELSE> {
type Out;
}
impl<THEN, ELSE> IfT<THEN, ELSE> for True {
type Out = THEN;
}
impl<THEN, ELSE> IfT<THEN, ELSE> for False {
type Out = ELSE;
}
type FizzBuzzSingle<N> = <N as FizzBuzzSingleT>::Out;
trait FizzBuzzSingleT {
type Out;
}
impl<N> FizzBuzzSingleT for N
where
N: DivisibleBy3T + DivisibleBy5T,
<N as DivisibleBy3T>::Out: AndT<<N as DivisibleBy5T>::Out>,
<N as DivisibleBy5T>::Out: IfT<Buzz, N>,
<N as DivisibleBy3T>::Out: AndT<<N as DivisibleBy5T>::Out>,
<N as DivisibleBy5T>::Out: IfT<Buzz, N>,
<N as DivisibleBy3T>::Out: IfT<Fizz, <<N as DivisibleBy5T>::Out as IfT<Buzz, N>>::Out>,
<<N as DivisibleBy3T>::Out as AndT<<N as DivisibleBy5T>::Out>>::Out: IfT<
FizzBuzz,
<<N as DivisibleBy3T>::Out as IfT<
Fizz,
<<N as DivisibleBy5T>::Out as IfT<Buzz, N>>::Out,
>>::Out,
>,
{
type Out = If<
And<DivisibleBy3<N>, DivisibleBy5<N>>,
FizzBuzz,
If<DivisibleBy3<N>, Fizz, If<DivisibleBy5<N>, Buzz, N>>,
>;
}
type RunFizzBuzz<N> = <N as RunFizzBuzzT>::Out;
trait RunFizzBuzzT {
type Out;
}
impl RunFizzBuzzT for Z {
type Out = Nil;
}
impl<N> RunFizzBuzzT for S<N>
where
N: RunFizzBuzzT,
N: DivisibleBy3T,
N: DivisibleBy5T,
<N as DivisibleBy3T>::Out: AndT<<N as DivisibleBy5T>::Out>,
<N as DivisibleBy5T>::Out: IfT<Buzz, N>,
<N as DivisibleBy3T>::Out: AndT<<N as DivisibleBy5T>::Out>,
<N as DivisibleBy5T>::Out: IfT<Buzz, N>,
<N as DivisibleBy3T>::Out: IfT<Fizz, <<N as DivisibleBy5T>::Out as IfT<Buzz, N>>::Out>,
<<N as DivisibleBy3T>::Out as AndT<<N as DivisibleBy5T>::Out>>::Out: IfT<
FizzBuzz,
<<N as DivisibleBy3T>::Out as IfT<
Fizz,
<<N as DivisibleBy5T>::Out as IfT<Buzz, N>>::Out,
>>::Out,
>,
<N as RunFizzBuzzT>::Out: AppendT<
<<<N as DivisibleBy3T>::Out as AndT<<N as DivisibleBy5T>::Out>>::Out as IfT<
FizzBuzz,
<<N as DivisibleBy3T>::Out as IfT<
Fizz,
<<N as DivisibleBy5T>::Out as IfT<Buzz, N>>::Out,
>>::Out,
>>::Out,
>,
{
type Out = Append<FizzBuzzSingle<N>, RunFizzBuzz<N>>;
}
fn main() -> RunFizzBuzz<N100> {
println!("Hello, world!");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment