Zulip Chat Archive
Stream: general
Topic: No confusion puzzle
Andrew Yang (Feb 01 2025 at 20:07):
Does anyone have a proof to this?
axiom F : Nat → Nat
inductive Foo : Nat → Type
| foo n : Foo (F n)
example (a b : Nat) (hab : F a = F b) (hab' : a ≠ b) :
Foo.foo a ≠ hab ▸ Foo.foo b := by sorry
Andrew Yang (Feb 01 2025 at 20:12):
And level two (which should have more or less the same proof and is the case that I need)
axiom F : Nat → Nat
inductive Foo : Nat → Type
| foo n : Foo (F n)
| bar n : Foo (F n)
example (a b : Nat) (hab : F a = F b) : Foo.foo a ≠ hab ▸ Foo.bar b := by sorry
Markus Himmel (Feb 01 2025 at 20:18):
Here is one way for the first one:
axiom F : Nat → Nat
inductive Foo : Nat → Type
| foo n : Foo (F n)
def Foo.out {n} : Foo n → Nat
| Foo.foo k => k
@[simp]
theorem Foo.out_mk {n} : (Foo.foo n).out = n := rfl
@[simp]
theorem Foo.out_cast {n m} (h : n = m) (f : Foo n) : (h ▸ f).out = f.out :=
by cases h; rfl
example (a b : Nat) (hab : F a = F b) (hab' : a ≠ b) :
Foo.foo a ≠ hab ▸ Foo.foo b := by
apply ne_of_apply_ne Foo.out
simpa using hab'
Markus Himmel (Feb 01 2025 at 20:23):
The second one works the same way:
axiom F : Nat → Nat
inductive Foo : Nat → Type
| foo n : Foo (F n)
| bar n : Foo (F n)
inductive Bar : Type
| foo (n : Nat) : Bar
| bar (n : Nat) : Bar
def Foo.out {n} : Foo n → Bar
| .foo n => .foo n
| .bar n => .bar n
@[simp] theorem Foo.out_foo {n} : (Foo.foo n).out = .foo n := rfl
@[simp] theorem Foo.out_bar {n} : (Foo.bar n).out = .bar n := rfl
@[simp] theorem Foo.out_cast {n m} (h : n = m) (f : Foo n) : (h ▸ f).out = f.out := by cases h; rfl
example (a b : Nat) (hab : F a = F b) : Foo.foo a ≠ hab ▸ Foo.bar b := by
apply ne_of_apply_ne Foo.out
simp
Andrew Yang (Feb 01 2025 at 20:28):
Great! (I originally tried a bijection with inductive Foo2 : Nat → Type | foo a b (h : F a = b) : Foo2 b
which works but is much more messy)
Is there a good way to achieve this without auxiliary defs? Or for every inductive type with inductive indices I need to define such an auxiliary inductive type to get the no-confusion lemmas?
Edward van de Meent (Feb 01 2025 at 21:16):
personally i'd try to avoid this kind of inductive... For example, you might be happier using inductive Bar where | foo n : Foo | bar n : Foo
, to then work with the subtype Foo x := {b : Bar| F b.out = x}
. When you need to rewrite , use a cast
function, such that the rewrites are cleaner and part of the object, as well as in a way that the kernel gets to forget when trying to match on the actual value.
Edward van de Meent (Feb 01 2025 at 21:18):
for a concrete usecase of this pattern, check out docs#List.Vector
Andrew Yang (Feb 01 2025 at 21:20):
The inductive in question is docs#CategoryTheory.Limits.WalkingMulticospan.Hom . And because it is constructing arrows in a category it needs to have type WalkingMulticospan fst snd → WalkingMulticospan fst snd → Type _
Edward van de Meent (Feb 01 2025 at 21:28):
i think strictly speaking my suggestion still works? the only thing i imagine people might take issue with is the fact that it mentions object equality, but i'm not a category theorist
Last updated: May 02 2025 at 03:31 UTC