diff --git a/fizzbuzz/types/main.rs b/fizzbuzz/types/main.rs new file mode 100644 index 0000000..a71bb46 --- /dev/null +++ b/fizzbuzz/types/main.rs @@ -0,0 +1,284 @@ +#![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(); +}