Zulip Chat Archive

Stream: new members

Topic: Nested inductive datatypes with vectors


James Parker (Apr 22 2025 at 22:01):

Hi. I'm attempting to write something along the lines of the following:

inductive Foo (f: Type) where
| Bar: (foos: Vector (Foo f) 3) -> Foo f

This results in the error invalid nested inductive datatype 'Eq', nested inductive datatypes parameters cannot contain local variables.. Can anyone explain why this errors, but switching the Vector to an Array works?

inductive Foo (f: Type) where
| Bar: (foos: Array (Foo f)) -> Foo f

Robin Arnez (Apr 22 2025 at 22:39):

Well, the answer is that Vector is a subtype and therefore contains a property on the recursion. However, it is not supported when a type within the constructor depends on another one with recursion. Take this variant:

inductive Foo (f : Type) where
  | Bar (foos : Array (Foo f)) (h : foos.size = 3) : Foo f

foos is recursive and it's being referenced in h. This is simply not allowed.
(I'm not 100% sure about the "why", maybe someone else can help with that)

James Parker (Apr 24 2025 at 17:22):

That's helpful, thanks! I didn't realize Vector was defined that way since its definition is hidden by the docs.

James Parker (Apr 24 2025 at 17:23):

It would be nice to understand why this isn't allowed. Is it unsound or is the type checker being conservative?

Robin Arnez (Apr 24 2025 at 20:01):

I guess one thing is that generally allowing this makes you lose the ability to translate between equivalent definitions:

unsafe inductive GenericProperty (α : Type u) (β : α  Type v) (p :  {γ}, (a : α)  (β a  γ)  Prop) where
  | mk (a : α) (f : β a  GenericProperty α β p) (h : p a f)

unsafe inductive GenericPropertyOther (α : Type u) (β : α  Type v) (p :  {γ}, (a : α)  (β a  γ)  Prop) where
  | mk (a : α) (f : β a  GenericPropertyOther α β p) (h : p a f)

unsafe def translate : GenericProperty α β p  GenericPropertyOther α β p
  | .mk a f h =>
    let g := fun x => translate (f x)
    .mk a g sorry -- have h : p a f, need p a g (impossible!)

Takes this other type in contrast:

inductive MyList (α : Type u) where
  | nil
  | cons (a : α) (l : MyList α)

def translate : List α  MyList α
  | .nil => .nil
  | .cons a l => .cons a (translate l)

Robin Arnez (Apr 24 2025 at 20:02):

I'm not sure whether this is unsound but ... probably..?


Last updated: May 02 2025 at 03:31 UTC