inductive Op : (inp out : List (Type u)) → Type (u+1) where | push (a : α) : Op s (α::s) | pop : Op (α::s) s | dup : Op (α::s) (α::α::s) | swap : Op (α::β::s) (β::α::s) | call : Op ((α → β)::α::s) (β::s) | seq (a : Op i o) (b : Op o o') : Op i o' abbrev Stack : List Type → Type | [] => Unit | t::ts => t × Stack ts example : (α × Stack s) = Stack (α::s) := by simp #reduce (types := true) Stack [Nat, Int, Int] def Op.run : Op i o → Stack i → Stack o | push x, t => (x, t) | pop, (x, s) => s | dup, (x, s) => (x, x, s) | swap, (a, b, s) => (b, a, s) | call, (f, a, s) => (f a, s) | seq a b, s => b.run (a.run s) def Op.runEmpty (op : Op [] o) : Stack o := op.run () #eval (Op.push 1) |>.seq (Op.push 2) |>.seq (Op.push Nat.add) |>.seq Op.call |>.seq Op.call |>.runEmpty def main : IO Unit := IO.println s!"Hello, world!"