#![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(PhantomData); impl Num for Succ { fn render() -> u64 { ::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(PhantomData, PhantomData); impl String for SCons { fn render() { print!("{}", ::render()); ::render(); } } struct SBadEval {} impl String for SBadEval { fn render() { print!("BAD EVAL"); } } trait StringifiedImpl: Num { type Result: String; } impl StringifiedImpl for N { default type Result = SBadEval; } impl StringifiedImpl for Zero { type Result = SCons; } impl StringifiedImpl for Succ { type Result = <::Result as StringIncrement>::Result; } trait Stringified: Num { type Result: String; } impl Stringified for N { type Result = <::Result as Rev>::Result; } trait StringIncrement: String { type Result: String; } impl StringIncrement for SEmpty { type Result = SCons; } impl StringIncrement for S { default type Result = SBadEval; } impl StringIncrement for SCons { type Result = SCons; } impl StringIncrement for SCons { type Result = SCons; } impl StringIncrement for SCons { type Result = SCons; } impl StringIncrement for SCons { type Result = SCons; } impl StringIncrement for SCons { type Result = SCons; } impl StringIncrement for SCons { type Result = SCons; } impl StringIncrement for SCons { type Result = SCons; } impl StringIncrement for SCons { type Result = SCons; } impl StringIncrement for SCons { type Result = SCons; } impl StringIncrement for SCons { type Result = SCons::Result>; } trait App: String { type Result: String; } impl App for T { default type Result = SBadEval; } impl App for SEmpty { type Result = S; } impl App for SCons { type Result = SCons>::Result>; } trait Rev: String { type Result: String; } impl Rev for S { default type Result = SBadEval; } impl Rev for SEmpty { type Result = SEmpty; } impl Rev for SCons { type Result = >>::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 NumMod3 for T { default type Result = ModBadEval; } impl NumMod3 for Zero { type Result = Mod; } impl NumMod3 for Succ { type Result = Modnt; } impl NumMod3 for Succ> { type Result = Modnt; } impl NumMod3 for Succ>> { type Result = ::Result; } trait NumMod5: Num { type Result: ModResult; } impl NumMod5 for T { default type Result = ModBadEval; } impl NumMod5 for Zero { type Result = Mod; } impl NumMod5 for Succ { type Result = Modnt; } impl NumMod5 for Succ> { type Result = Modnt; } impl NumMod5 for Succ>> { type Result = Modnt; } impl NumMod5 for Succ>>> { type Result = Modnt; } impl NumMod5 for Succ>>>> { type Result = ::Result; } trait FizzbuzzStringified: Num { type Result: String; } trait FbstrHelper: Num { type Result: String; } impl FbstrHelper for T { default type Result = SBadEval; } impl FbstrHelper for T { type Result = ::Result; } impl FbstrHelper for T { type Result = SCons>>>; } impl FbstrHelper for T { type Result = SCons>>>; } impl FbstrHelper for T { type Result = SCons>>>>>>>; } impl FizzbuzzStringified for T { type Result = ::Result, ::Result>>::Result; } trait Added: Num { type Result: Num; } impl Added for T { default type Result = S; } impl Added for Zero { type Result = S; } impl Added for Succ { type Result = Succ<>::Result>; } trait FizzbuzzProgram: Num { type Result: String; } impl FizzbuzzProgram for T { default type Result = SBadEval; } impl FizzbuzzProgram for Zero { type Result = SEmpty; } impl FizzbuzzProgram for Succ { type Result = <<::Result as App< as FizzbuzzStringified>::Result>>::Result as App>>::Result; } fn main() { type One = Succ; type Two = Succ; type Four = >::Result; type Eight = >::Result; type Sixteen = >::Result; type Five = >::Result; type Ten = >::Result; type Thirty = <<>::Result as Added>::Result as Added>::Result; type OneHundred = <<>::Result as Added>::Result as Added>::Result; ::Result::render(); }