Skip to content

Instantly share code, notes, and snippets.

@joonazan
Created January 18, 2026 23:44
Show Gist options
  • Select an option

  • Save joonazan/b24aea422ab540f10a087e0f76f9db30 to your computer and use it in GitHub Desktop.

Select an option

Save joonazan/b24aea422ab540f10a087e0f76f9db30 to your computer and use it in GitHub Desktop.
struct One;
struct Succ<T>(T);
trait Pos {
type Add<Other: Pos>: Pos;
}
impl Pos for One {
type Add<Other: Pos> = Succ<Other>;
}
impl<T: Pos> Pos for Succ<T> {
type Add<Other: Pos> = Succ<T::Add<Other>>;
}
struct Stack<N, I>(N, I);
struct EmptyStack;
struct IronOre;
struct Iron;
struct CopperOre;
struct Copper;
struct Furnace<In, Out, Time>(In, Out, Time);
trait FurnaceInsert<S> {
type Ret;
fn insert(self, stack: S) -> Self::Ret;
}
impl<N, I, Out, T> FurnaceInsert<Stack<N, I>> for Furnace<EmptyStack, Out, T> {
type Ret = Furnace<Stack<N, I>, Out, T>;
fn insert(self, _: Stack<N, I>) -> Self::Ret {
todo!()
}
}
impl<I, N: Pos, N2: Pos, Out, T> FurnaceInsert<Stack<N, I>> for Furnace<Stack<N2, I>, Out, T> {
type Ret = Furnace<Stack<N::Add<N2>, I>, Out, T>;
fn insert(self, _: Stack<N, I>) -> Self::Ret {
todo!()
}
}
trait FurnaceTick {
type Next;
}
impl<O, T: Pos> FurnaceTick for Furnace<EmptyStack, O, T> {
type Next = Furnace<EmptyStack, O, Succ<T>>;
}
impl<N2, I, T: Pos> FurnaceTick for Furnace<Stack<One, I>, Stack<N2, I>, T> {
type Next = Furnace<EmptyStack, Stack<Succ<N2>, I>, Succ<T>>;
}
impl<N, N2, I, T> FurnaceTick for Furnace<Stack<Succ<N>, I>, Stack<N2, I>, T>{
type Next = Furnace<Stack<N, I>, Stack<Succ<N2>, I>, Succ<T>>;
}
// There are cursed unsound? ways to do type inequality without listing all cases
// Specialization would solve this nicely if it was properly implemented some time
impl<N, N2, T> FurnaceTick for Furnace<Stack<N, IronOre>, Stack<N2, Copper>, T>{
type Next = Furnace<Stack<N, IronOre>, Stack<N2, Copper>, Succ<T>>;
}
// ...
trait FurnacePassTime<D> {
type After;
fn pass_time(self) -> Self::After;
}
impl<T: FurnaceTick> FurnacePassTime<One> for T {
type After = T::Next;
fn pass_time(self) -> Self::After {
todo!()
}
}
impl<T: FurnaceTick, D> FurnacePassTime<Succ<D>> for T
where T::Next: FurnacePassTime<D>
{
type After = <T::Next as FurnacePassTime<D>>::After;
fn pass_time(self) -> Self::After {
todo!()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment