inductive Op : (inp out : Array (Type u)) → Type (u+1) where | push (a : α) : Op #[] #[α] | pop {α : Type u} : Op #[α] #[] | dup {α : Type u} : Op #[α] #[α, α] | swap {α β : Type u} : Op #[α, β] #[β, α] | call (f : α → β) : Op #[α] #[β] | seq (a : Op i o) (b : Op o o') : Op i o' instance : HAndThen (Op i o) (Op o o') (Op i o') where hAndThen a b := Op.seq a (b ()) abbrev Stack : Array Type → Type | ⟨[]⟩ => Unit | ⟨[t]⟩ => t | ⟨t::ts⟩ => t × Stack ⟨ts⟩ #reduce (types := true) Stack #[Nat, Int, Int] def Op.run : Op i o → Stack i → Stack o | push x, () => x | pop, _ => () | dup, x => (x, x) | swap, (a, b) => (b, a) | call f, x => f x | seq a b, s => b.run (a.run s) #eval Op.push 1 >> Op.call Nat.succ |>.run () def main : IO Unit := IO.println s!"Hello, world!"