Zulip Chat Archive
Stream: lean4
Topic: Defining an dependently-typed recursive inductive data type
Andrew (Aug 12 2025 at 12:42):
Hi everyone! I am trying to define an inductive datatype that represents natural-number literals an n-ary operators on them. However, Lean is rejecting my datatype with the error message (kernel) invalid nested inductive datatype 'Vector', nested inductive datatypes parameters cannot contain local variables.. I've attached an #mwe here. Could anyone give a suggestion on how to make this type work?
Kenny Lau (Aug 12 2025 at 12:50):
@Andrew you can include the code using #backticks, which already generates a link to the website (on the top right hand corner of the code block)
Andrew (Aug 12 2025 at 12:52):
import Mathlib.Data.Vector.Basic
inductive NumericExpression where
| numericLiteral : Nat -> NumericExpression
| operation : (n : Nat) -> (Vector Nat n -> Nat) -> (Vector NumericExpression n) -> NumericExpression
Andrew (Aug 12 2025 at 12:53):
Even more minimal #mwe here:
import Mathlib.Data.Vector.Basic
inductive NumericExpression where
| operation : (Vector NumericExpression 3) -> NumericExpression
Kenny Lau (Aug 12 2025 at 12:55):
you forgot to include the definition of MyVector
Andrew (Aug 12 2025 at 12:55):
Just changed it, I'm using the standard library vector, MyVector was just for debugging
Jovan Gerbscheid (Aug 12 2025 at 15:51):
It works with List, and I think also with Array, but Vector is not supported yet for constructing inductive types through it. This is a limitation in the current implementation of inductive types. In the new year 3 roadmap it says that inductive will be fixed so that HashMap and TreeMap are supported here. I assume that this will also fix it for Vector.
Andrew (Aug 12 2025 at 18:46):
Thanks!
Phil Nguyen (Aug 12 2025 at 18:46):
I ran into a similar problem a while ago. It turns out Vector or refined types aren't supported yet. A current suggested solution would be something like Fin n -> NumericExpression:
inductive NumericExpression where
| numericLiteral : Nat -> NumericExpression
| operation : (n : Nat) -> (Vector Nat n -> Nat) -> (Fin n → NumericExpression) -> NumericExpression
But if you'd prefer a first-order, more readily inspectable representation, you could also try mutually defining NumericExpressionList : Nat -> Type:
mutual
inductive NumericExpression : Type u where
| numericLiteral : Nat -> NumericExpression
| operation : (n : Nat) -> (Vector Nat n -> Nat) -> NumericExpressionList n -> NumericExpression
inductive NumericExpressionList : Nat → Type u where
| nil : NumericExpressionList 0
| cons : NumericExpression → NumericExpressionList n → NumericExpressionList (n + 1)
end
These solutions are sub-optimal (e.g. boilerplate, poor locality, etc.). But I think they'll improve this coming year.
Jovan Gerbscheid (Aug 12 2025 at 20:10):
(Note also that you don't need to import Mathlib.Data.Vector.Basic, as Vector is defined in Std)
Last updated: Dec 20 2025 at 21:32 UTC