Zulip Chat Archive
Stream: general
Topic: A Type 1 inductive type
Tanner Swett (Jul 03 2023 at 03:49):
I feel like I just leveled up: I just wrote my first ever inductive type that required me to use a higher universe, and it's also my first ever mutually inductive type :big_smile:
Here it is:
mutual
inductive StackFrame : (α β : Type) → Type 1 where
| eval : StackFrame Expr Expr
| func {α β γ : Type} (f : α → β) (g : α → Stack β γ) : StackFrame α γ
inductive Stack : (α β : Type) → Type 1 where
| empty (α : Type) : Stack α α
| push {α β γ : Type} (top : StackFrame α β) (rest : Stack β γ) : Stack α γ
end
The type Stack
here represents a call stack. A func
stack frame consists of two components: a function to run immediately to produce an intermediate result, and a function producing a collection of stack frames which will further process the intermediate result.
This _does_ need to be in Type 1
, right? A Stack
can contain functions with arbitrary domain and codomain types, which means that a Stack
needs to contain Type
s, and anything with Type
s in it has to live in Type 1
or higher.
Mario Carneiro (Jul 03 2023 at 04:15):
Yes, this has to be in Type 1
as written, although usually this is a bad sign / to be avoided. Usually you can avoid it in this kind of situation by classifying some family of types that you actually care to consider, which can be indexed by a normal inductive type instead of by a universe
Tanner Swett (Jul 03 2023 at 04:23):
Yup. I figured it would be cool to be able to write implementation functions in do notation, which means I need a monad, and I've discovered that that means that the call stack can get "polluted" with arbitrary types, so I need this.
Last updated: Dec 20 2023 at 11:08 UTC