Zulip Chat Archive
Stream: new members
Topic: Type unification question
Julia Scheaffer (Sep 01 2025 at 20:59):
I am currently working on a formalizing a stack in Lean, but I am having some trouble convincing Lean that my some of the types are in fact the same. Here are some of the relevant definitions:
/-- A typed heterogeneous stack -/
inductive Stack.{u} : List (Type u) -> Type (u + 1) where
| nil : Stack []
| cons {α β}: α -> Stack β -> Stack (α :: β)
infixr:67 "; " => Stack.cons
def Stack.append.{u} {α β : List (Type u)} : Stack α -> Stack β -> Stack (α ++ β)
| nil, b => b | head; tail, b => head; Stack.append tail b
I would like to try proving that {α : List (Type u)} -> (a : Stack α) -> a.append Stack.nil = a but the compiler complains that Stack (α ++ []) does not match Stack α. Is there a way I can tell lean that these two are the same? (I have proven it's equality) Is the fact that these two types are not judgmentally equal stopping it form working?
Aaron Liu (Sep 01 2025 at 21:02):
I think you should not be trying to prove that a.append Stack.nil = a
Aaron Liu (Sep 01 2025 at 21:03):
also have you seen docs#List.TProd
Julia Scheaffer (Sep 01 2025 at 21:05):
I discovered List.TProd after I wrote this code unfortunately. :sweat_smile:
Julia Scheaffer (Sep 01 2025 at 21:07):
If I were to rewrite my Stack using List.TProd, for the type family α I think I would want to just use id, right?
Aaron Liu (Sep 01 2025 at 21:08):
What I did is I wrote a get function
Aaron Liu said:
import Mathlib def List.TProd.get {ι : Type u} {α : ι → Type v} {l : List ι} (t : l.TProd α) (n : Nat) (i : ι) (hi : i ∈ l[n]?) : α i := match l, n, hi with | _ :: _, 0, rfl => t.1 | _ :: _, n + 1, hi => List.TProd.get t.2 n i hi
and then I proved get_append_of_lt and get_append_of_ge
Julia Scheaffer (Sep 01 2025 at 21:14):
I will try to take that approach instead, thanks. I was hoping to get away with my slightly simpler definition, but TProd will probably end up being better in the long run.
Julia Scheaffer (Sep 02 2025 at 02:49):
Julia Scheaffer said:
I will try to take that approach instead, thanks. I was hoping to get away with my slightly simpler definition, but TProd will probably end up being better in the long run.
I cannot get my code working with List.TProd today. I might try it again another day with some fresh perspective.
Julia Scheaffer (Sep 02 2025 at 02:52):
Is it impossible to convince lean that Stack (α ++ []) and Stack α are compatible types like in my first message? If not I will have to do something else to state these theorems :/
pandaman (Sep 02 2025 at 04:44):
You can lift the pattern to an equality proposition. It's a bit cumbersome, but at least it can avoid dependent pattern match failures.
/-- A typed heterogeneous stack -/
inductive Stack.{u} : List (Type u) -> Type (u + 1) where
| nil : Stack []
| cons {α β ts} : α -> Stack β → (ts = α :: β) -> Stack ts
-- infixr:67 "; " => Stack.cons
def Stack.append.{u} {α β : List (Type u)} : Stack α -> Stack β -> Stack (α ++ β)
| nil, b => b
| cons a b h, b' => .cons a (append b b') (by simp [h])
pandaman (Sep 02 2025 at 04:49):
Ah sorry, I misunderstood the question. I think we need something like Stack.cast(see )
Julia Scheaffer (Sep 02 2025 at 13:01):
pandaman said:
Ah sorry, I misunderstood the question. I think we need something like
Stack.cast(see )
Thank you for this advice. I will try that out.
Julia Scheaffer (Sep 02 2025 at 17:12):
Thank you for the recommendation @pandaman. I got have some proofs about Stack.append working now!
Also thanks to @Kyle Miller for those Vec exercises, they were a huge help for figuring out how to work with cast.
Last updated: Dec 20 2025 at 21:32 UTC