285 lines
7.1 KiB
Rust
285 lines
7.1 KiB
Rust
|
#![recursion_limit = "1024"]
|
||
|
#![feature(specialization)]
|
||
|
use std::marker::PhantomData;
|
||
|
|
||
|
trait Num { fn render() -> u64; }
|
||
|
struct Zero;
|
||
|
impl Num for Zero { fn render() -> u64 { 0 } }
|
||
|
struct Succ<I: Num>(PhantomData<I>);
|
||
|
impl<I: Num> Num for Succ<I> { fn render() -> u64 { <I>::render() + 1 } }
|
||
|
|
||
|
|
||
|
trait Char { fn render() -> char; }
|
||
|
struct S0 {} impl Char for S0 { fn render() -> char { '0' } }
|
||
|
struct S1 {} impl Char for S1 { fn render() -> char { '1' } }
|
||
|
struct S2 {} impl Char for S2 { fn render() -> char { '2' } }
|
||
|
struct S3 {} impl Char for S3 { fn render() -> char { '3' } }
|
||
|
struct S4 {} impl Char for S4 { fn render() -> char { '4' } }
|
||
|
struct S5 {} impl Char for S5 { fn render() -> char { '5' } }
|
||
|
struct S6 {} impl Char for S6 { fn render() -> char { '6' } }
|
||
|
struct S7 {} impl Char for S7 { fn render() -> char { '7' } }
|
||
|
struct S8 {} impl Char for S8 { fn render() -> char { '8' } }
|
||
|
struct S9 {} impl Char for S9 { fn render() -> char { '9' } }
|
||
|
|
||
|
struct SF {} impl Char for SF { fn render() -> char { 'F' } }
|
||
|
struct Si {} impl Char for Si { fn render() -> char { 'i' } }
|
||
|
struct Sz {} impl Char for Sz { fn render() -> char { 'z' } }
|
||
|
struct SB {} impl Char for SB { fn render() -> char { 'B' } }
|
||
|
struct Su {} impl Char for Su { fn render() -> char { 'u' } }
|
||
|
struct Snl {} impl Char for Snl { fn render() -> char { '\n' } }
|
||
|
|
||
|
|
||
|
trait String { fn render(); }
|
||
|
struct SEmpty {} impl String for SEmpty { fn render() {} }
|
||
|
struct SCons<F: Char, R: String>(PhantomData<F>, PhantomData<R>);
|
||
|
impl<F: Char, R: String> String for SCons<F, R> {
|
||
|
fn render() {
|
||
|
print!("{}", <F>::render());
|
||
|
<R>::render();
|
||
|
}
|
||
|
}
|
||
|
struct SBadEval {}
|
||
|
impl String for SBadEval { fn render() { print!("BAD EVAL"); } }
|
||
|
|
||
|
trait StringifiedImpl: Num {
|
||
|
type Result: String;
|
||
|
}
|
||
|
|
||
|
impl<N: Num> StringifiedImpl for N {
|
||
|
default type Result = SBadEval;
|
||
|
}
|
||
|
|
||
|
impl StringifiedImpl for Zero {
|
||
|
type Result = SCons<S0, SEmpty>;
|
||
|
}
|
||
|
|
||
|
impl<N: Num> StringifiedImpl for Succ<N> {
|
||
|
type Result = <<N as StringifiedImpl>::Result as StringIncrement>::Result;
|
||
|
}
|
||
|
|
||
|
trait Stringified: Num {
|
||
|
type Result: String;
|
||
|
}
|
||
|
|
||
|
impl<N: Num> Stringified for N {
|
||
|
type Result = <<N as StringifiedImpl>::Result as Rev>::Result;
|
||
|
}
|
||
|
|
||
|
trait StringIncrement: String {
|
||
|
type Result: String;
|
||
|
}
|
||
|
|
||
|
impl StringIncrement for SEmpty {
|
||
|
type Result = SCons<S1, SEmpty>;
|
||
|
}
|
||
|
|
||
|
impl<S: String> StringIncrement for S {
|
||
|
default type Result = SBadEval;
|
||
|
}
|
||
|
|
||
|
impl<S: String> StringIncrement for SCons<S0, S> {
|
||
|
type Result = SCons<S1, S>;
|
||
|
}
|
||
|
impl<S: String> StringIncrement for SCons<S1, S> {
|
||
|
type Result = SCons<S2, S>;
|
||
|
}
|
||
|
impl<S: String> StringIncrement for SCons<S2, S> {
|
||
|
type Result = SCons<S3, S>;
|
||
|
}
|
||
|
impl<S: String> StringIncrement for SCons<S3, S> {
|
||
|
type Result = SCons<S4, S>;
|
||
|
}
|
||
|
impl<S: String> StringIncrement for SCons<S4, S> {
|
||
|
type Result = SCons<S5, S>;
|
||
|
}
|
||
|
impl<S: String> StringIncrement for SCons<S5, S> {
|
||
|
type Result = SCons<S6, S>;
|
||
|
}
|
||
|
impl<S: String> StringIncrement for SCons<S6, S> {
|
||
|
type Result = SCons<S7, S>;
|
||
|
}
|
||
|
impl<S: String> StringIncrement for SCons<S7, S> {
|
||
|
type Result = SCons<S8, S>;
|
||
|
}
|
||
|
impl<S: String> StringIncrement for SCons<S8, S> {
|
||
|
type Result = SCons<S9, S>;
|
||
|
}
|
||
|
impl<S: String + StringIncrement> StringIncrement for SCons<S9, S> {
|
||
|
type Result = SCons<S0, <S as StringIncrement>::Result>;
|
||
|
}
|
||
|
|
||
|
trait App<S: String>: String {
|
||
|
type Result: String;
|
||
|
}
|
||
|
|
||
|
impl<S: String, T: String> App<S> for T {
|
||
|
default type Result = SBadEval;
|
||
|
}
|
||
|
|
||
|
impl<S: String> App<S> for SEmpty {
|
||
|
type Result = S;
|
||
|
}
|
||
|
|
||
|
impl<S: String, F: Char, R: String> App<S> for SCons<F, R> {
|
||
|
type Result = SCons<F, <R as App<S>>::Result>;
|
||
|
}
|
||
|
|
||
|
trait Rev: String {
|
||
|
type Result: String;
|
||
|
}
|
||
|
|
||
|
impl<S: String> Rev for S {
|
||
|
default type Result = SBadEval;
|
||
|
}
|
||
|
|
||
|
impl Rev for SEmpty {
|
||
|
type Result = SEmpty;
|
||
|
}
|
||
|
|
||
|
impl<F: Char, R: String> Rev for SCons<F, R> {
|
||
|
type Result = <R as App<SCons<F, SEmpty>>>::Result;
|
||
|
}
|
||
|
|
||
|
trait ModResult { fn render(); }
|
||
|
struct ModBadEval {} impl ModResult for ModBadEval { fn render() { println!("mod bad eval"); } }
|
||
|
struct Mod {} impl ModResult for Mod { fn render() { println!("mod"); } }
|
||
|
struct Modnt {} impl ModResult for Modnt { fn render() { println!("not mod"); } }
|
||
|
|
||
|
trait NumMod3: Num {
|
||
|
type Result: ModResult;
|
||
|
}
|
||
|
|
||
|
impl<T: Num> NumMod3 for T {
|
||
|
default type Result = ModBadEval;
|
||
|
}
|
||
|
|
||
|
impl NumMod3 for Zero {
|
||
|
type Result = Mod;
|
||
|
}
|
||
|
|
||
|
impl NumMod3 for Succ<Zero> {
|
||
|
type Result = Modnt;
|
||
|
}
|
||
|
|
||
|
impl NumMod3 for Succ<Succ<Zero>> {
|
||
|
type Result = Modnt;
|
||
|
}
|
||
|
|
||
|
impl<T: Num> NumMod3 for Succ<Succ<Succ<T>>> {
|
||
|
type Result = <T as NumMod3>::Result;
|
||
|
}
|
||
|
|
||
|
trait NumMod5: Num {
|
||
|
type Result: ModResult;
|
||
|
}
|
||
|
|
||
|
impl<T: Num> NumMod5 for T {
|
||
|
default type Result = ModBadEval;
|
||
|
}
|
||
|
|
||
|
impl NumMod5 for Zero {
|
||
|
type Result = Mod;
|
||
|
}
|
||
|
|
||
|
impl NumMod5 for Succ<Zero> {
|
||
|
type Result = Modnt;
|
||
|
}
|
||
|
|
||
|
impl NumMod5 for Succ<Succ<Zero>> {
|
||
|
type Result = Modnt;
|
||
|
}
|
||
|
|
||
|
impl NumMod5 for Succ<Succ<Succ<Zero>>> {
|
||
|
type Result = Modnt;
|
||
|
}
|
||
|
|
||
|
impl NumMod5 for Succ<Succ<Succ<Succ<Zero>>>> {
|
||
|
type Result = Modnt;
|
||
|
}
|
||
|
|
||
|
impl<T: Num> NumMod5 for Succ<Succ<Succ<Succ<Succ<T>>>>> {
|
||
|
type Result = <T as NumMod5>::Result;
|
||
|
}
|
||
|
|
||
|
|
||
|
trait FizzbuzzStringified: Num {
|
||
|
type Result: String;
|
||
|
}
|
||
|
|
||
|
trait FbstrHelper<Mod3: ModResult, Mod5: ModResult>: Num {
|
||
|
type Result: String;
|
||
|
}
|
||
|
|
||
|
impl<T: Num, Mod3: ModResult, Mod5: ModResult> FbstrHelper<Mod3, Mod5> for T {
|
||
|
default type Result = SBadEval;
|
||
|
}
|
||
|
|
||
|
impl<T: Num> FbstrHelper<Modnt, Modnt> for T {
|
||
|
type Result = <T as Stringified>::Result;
|
||
|
}
|
||
|
|
||
|
impl<T: Num> FbstrHelper<Mod, Modnt> for T {
|
||
|
type Result = SCons<SF, SCons<Si, SCons<Sz, SCons<Sz, SEmpty>>>>;
|
||
|
}
|
||
|
|
||
|
impl<T: Num> FbstrHelper<Modnt, Mod> for T {
|
||
|
type Result = SCons<SB, SCons<Su, SCons<Sz, SCons<Sz, SEmpty>>>>;
|
||
|
}
|
||
|
|
||
|
impl<T: Num> FbstrHelper<Mod, Mod> for T {
|
||
|
type Result = SCons<SF, SCons<Si, SCons<Sz, SCons<Sz, SCons<SB, SCons<Su, SCons<Sz, SCons<Sz, SEmpty>>>>>>>>;
|
||
|
}
|
||
|
|
||
|
impl<T: Num> FizzbuzzStringified for T {
|
||
|
type Result = <T as FbstrHelper<<T as NumMod3>::Result, <T as NumMod5>::Result>>::Result;
|
||
|
}
|
||
|
|
||
|
trait Added<S: Num>: Num {
|
||
|
type Result: Num;
|
||
|
}
|
||
|
|
||
|
impl<T: Num, S: Num> Added<S> for T {
|
||
|
default type Result = S;
|
||
|
}
|
||
|
|
||
|
impl<S: Num> Added<S> for Zero {
|
||
|
type Result = S;
|
||
|
}
|
||
|
|
||
|
impl<T: Num, S: Num> Added<S> for Succ<T> {
|
||
|
type Result = Succ<<T as Added<S>>::Result>;
|
||
|
}
|
||
|
|
||
|
|
||
|
trait FizzbuzzProgram: Num {
|
||
|
type Result: String;
|
||
|
}
|
||
|
|
||
|
impl<T: Num> FizzbuzzProgram for T {
|
||
|
default type Result = SBadEval;
|
||
|
}
|
||
|
|
||
|
impl FizzbuzzProgram for Zero {
|
||
|
type Result = SEmpty;
|
||
|
}
|
||
|
|
||
|
impl<T: Num> FizzbuzzProgram for Succ<T> {
|
||
|
type Result = <<<T as FizzbuzzProgram>::Result as App<<Succ<T> as FizzbuzzStringified>::Result>>::Result as App<SCons<Snl, SEmpty>>>::Result;
|
||
|
}
|
||
|
|
||
|
|
||
|
fn main() {
|
||
|
type One = Succ<Zero>;
|
||
|
type Two = Succ<One>;
|
||
|
type Four = <Two as Added<Two>>::Result;
|
||
|
type Eight = <Four as Added<Four>>::Result;
|
||
|
type Sixteen = <Eight as Added<Eight>>::Result;
|
||
|
|
||
|
type Five = <Four as Added<One>>::Result;
|
||
|
type Ten = <Five as Added<Five>>::Result;
|
||
|
type Thirty = <<<Sixteen as Added<Eight>>::Result as Added<Four>>::Result as Added<Two>>::Result;
|
||
|
type OneHundred = <<<Thirty as Added<Thirty>>::Result as Added<Thirty>>::Result as Added<Ten>>::Result;
|
||
|
|
||
|
<OneHundred as FizzbuzzProgram>::Result::render();
|
||
|
}
|