Created
July 27, 2020 23:24
-
-
Save io12/ce6d2e9075bbbb7c294af5b58dd582ba 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
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