Zulip Chat Archive

Stream: lean4

Topic: nested inductive datatypes parameters cannot contain local v


Adrien Champion (Jan 13 2023 at 13:53):

Here is a tiny example of a problem I ran into recently

inductive Ty
  | bool
  | nat
def Ty.type : Ty  Type
  | .bool => Bool
  | .nat => Nat

inductive E₁ : Ty  Type
| cst {ty : Ty} : ty.type  E₁ ty
| eq {ty : Ty} : E₁ ty  E₁ ty  E₁ Ty.bool
-- no problem

inductive E₂ : Ty  Type
| cst {ty : Ty} : ty.type  E₂ ty
| app {ty : Ty} : (op : String)  (args : Array (E₂ ty))  E₂ ty
-- no problem

inductive E₃ : Ty  Type
| cst {ty : Ty} : ty.type  E₃ ty
| eq {ty : Ty} : E₃ ty  E₃ ty  E₃ Ty.bool
| app {ty : Ty} : (op : String)  (args : Array (E₃ ty))  E₃ ty
-- (kernel) invalid nested inductive datatype 'Array',
-- nested inductive datatypes parameters cannot contain local variables.

Adrien Champion (Jan 13 2023 at 13:53):

I found a handful of discussions that are somewhat related:

But even after reading them, I'm not sure what precisely the problem is in my example and how to solve it assuming it's possible.

Adrien Champion (Jan 13 2023 at 13:54):

Admittedly it's probably because I'm still too much of a Lean noob to actually understand these discussions fully, so any direct help or pointers to related discussions elsewhere would be greatly appreciated :smile:

Mario Carneiro (Jan 13 2023 at 14:23):

What is happening is that the presence of the eq constructor is making ty have to be treated as an index of the inductive type instead of a parameter. (In lean 3, the parameters all came before the colon in the inductive type declaration and the indices after, but lean 4 tries to be clever and promote indices to parameters when it can.)

Mario Carneiro (Jan 13 2023 at 14:26):

That's only half of the error though, the other half is that the nested inductive checker does not accept inductives which depend on local variables like ty here. I think this is not an essential constraint, and the checker could accept nested inductive families, but this is a very thorny part of the theory and I would prefer to be conservative without an explicit proof that it's sound to do this

Siddharth Bhat (Jan 13 2023 at 14:27):

Is this the MWE, or can it be made smaller?

inductive Const : Type _ | mk

inductive Const1 (t: Type _) : Type _ | mk : Const1 t

inductive E₃ : Const  Type
| mk : {c : Const}  (args : Const1 (E₃ c))  E₃ Const.mk

Adrien Champion (Jan 13 2023 at 14:28):

Mario Carneiro said:

What is happening is that the presence of the eq constructor is making ty have to be treated as an index of the inductive type instead of a parameter. (In lean 3, the parameters all came before the colon in the inductive type declaration and the indices after, but lean 4 tries to be clever and promote indices to parameters when it can.)

That's quite helpful thanks. I did not know about this distinction between parameters and indices

Mario Carneiro (Jan 13 2023 at 14:28):

Indeed the following mutual inductive is accepted

mutual
inductive E₃ : Ty  Type
| cst {ty : Ty} : ty.type  E₃ ty
| eq {ty : Ty} : E₃ ty  E₃ ty  E₃ Ty.bool
| app {ty : Ty} : (op : String)  (args : List_E₃ ty)  E₃ ty

inductive List_E₃ : Ty  Type
| nil : List_E₃ ty
| cons : E₃ ty  List_E₃ ty  List_E₃ ty
end

so I think it is an issue in the checker (which is trying to verify that the reduction to this mutual inductive is legal)

Adrien Champion (Jan 13 2023 at 14:29):

For readers that want to learn more about indices/parameters, I found the answer for this SO post helpful:

Adrien Champion (Jan 14 2023 at 10:54):

Mario Carneiro said:

so I think it is an issue in the checker (which is trying to verify that the reduction to this mutual inductive is legal)

Are you saying that the error I get is not expected in the sense that the checker could/should see there's such a reduction, and accept the original code with the standard List/Array types?

Mario Carneiro (Jan 14 2023 at 12:37):

yes, at least from my cursory reading of it

Mario Carneiro (Jan 14 2023 at 12:40):

My knowledge of the nested inductive checker is only indirect, I haven't read the code and there isn't really any spec for it besides what I've said so far (Sebastian's thesis extends #leantt to include lean 4 features but I don't think it covers the nested inductive checker in full detail - things get pretty hairy when you write it all down)


Last updated: Dec 20 2023 at 11:08 UTC