Zulip Chat Archive
Stream: lean4
Topic: Defining tree with dependent branching factor
Phil Nguyen (Mar 16 2025 at 01:55):
Suppose I want to model terms of a (first-order, untyped) language, but still want to statically track that applications have the right arities:
/-- Functions / base constants -/
structure Const (arity : Nat) where
name : String
/-- A term is either a variable, or an application of a function symbol to sub-terms -/
inductive Term where
| app : Const n → {args : Array Term // args.size = n} → Term
| var : String → Term
But I'll get an error:
(kernel) invalid nested inductive datatype 'Subtype', nested inductive datatypes parameters cannot contain local variables.
How should I fix this problem? Thanks!!
Aaron Liu (Mar 16 2025 at 02:01):
Using Fin n → Term
works
Phil Nguyen (Mar 16 2025 at 02:25):
That works great thanks! I needed a few coersion instances to make things look nice but that's neat.
Is this problem fundamental, or more of a current implementation quirk that may eventually be improved? Thanks!
Yury G. Kudryashov (Mar 16 2025 at 04:46):
Note that n
is an autoimplicit parameter here, so app
has type ∀ {n : Nat}, ...
Yury G. Kudryashov (Mar 16 2025 at 04:47):
Also, why do you need a structure Const
that takes arity
but doesn't use it in any way?
Yury G. Kudryashov (Mar 16 2025 at 04:52):
See https://github.com/leanprover/lean4/issues/1964
Phil Nguyen (Mar 16 2025 at 06:53):
Thanks Yury for the issue link!
The arity
was to avoid simple errors mis-applying the constant/function to the wrong number of arguments. For example:
abbrev MkTerm : Nat → Type
| 0 => Term
| n + 1 => Term → MkTerm n
-- For nicer term construction
instance : Coe String Term where coe := Term.var
instance : CoeFun (Const n) (λ _ => MkTerm n) where coe := /- omitted -/
def pair : Const 2 := ⟨"pair"⟩
def nil : Const 0 := ⟨"nil"⟩
def example : Term := pair (pair "x" "y") nil
Also, independent of whether I'll actually need to use the n
at runtime for this example, is there in general a way to mark an index as "compile-time only", so if I accidentally retain it at runtime, I'll get an error, similar to multiplicities in Idris? Thanks!!
Phil Nguyen (Mar 16 2025 at 07:08):
Ohh now I realized Yury's question was why I hadn't done it this way, which would reuse the arity
in Const
and avoid the implicit n
in Term.app
. Thanks!!
structure Const where
name : String
arity : Nat
inductive Term where
| app : (c : Const) → (Fin c.arity → Term) → Term
| var : String → Term
Yury G. Kudryashov (Mar 16 2025 at 14:16):
Note that this is nice for proving theorems but it's bad for writing computable code.
Yury G. Kudryashov (Mar 16 2025 at 14:16):
I mean, Fin _ → _
isn't stored as an array in memory.
Yury G. Kudryashov (Mar 16 2025 at 14:18):
I tried to give a mutual inductive
definition that stores children in an Array
but failed.
Last updated: May 02 2025 at 03:31 UTC