l3lab/ntp-mathlib huggingface dataset:
/-- If `r` is invertible and `s = r` and `si = ⅟r`, then `s` is invertible with `⅟s = si`. -/
def Invertible.copy' [MulOneClass α] {r : α} (hr : Invertible r) (s : α) (si : α) (hs : s = r)
    (hsi : si = ⅟ r) : Invertible s where
  invOf := si
  invOf_mul_self := by rw [hs, hsi, invOf_mul_self]
  mul_invOf_self := by 

Proof state:
α : Type u
inst✝ : MulOneClass α
r : α
hr : Invertible r
s si : α
hs : s = r
hsi : si = ⅟r
⊢ s * si = 1

Next tactic:
rw [hs, hsi, mul_invOf_self]
/-- `⅟b * ⅟a` is the inverse of `a * b` -/
def invertibleMul [Monoid α] (a b : α) [Invertible a] [Invertible b] : Invertible (a * b) :=
  ⟨⅟ b * ⅟ a, by 

Proof state:
α : Type u
inst✝² : Monoid α
a b : α
inst✝¹ : Invertible a
inst✝ : Invertible b
⊢ ⅟b * ⅟a * (a * b) = 1

Next tactic:
simp [← mul_assoc]
/-- `⅟b * ⅟a` is the inverse of `a * b` -/
def invertibleMul [Monoid α] (a b : α) [Invertible a] [Invertible b] : Invertible (a * b) :=
  ⟨⅟ b * ⅟ a, by simp [← mul_assoc], by 

Proof state:
α : Type u
inst✝² : Monoid α
a b : α
inst✝¹ : Invertible a
inst✝ : Invertible b
⊢ a * b * (⅟b * ⅟a) = 1

Next tactic:
simp [← mul_assoc]
@[simp]
theorem invOf_mul [Monoid α] (a b : α) [Invertible a] [Invertible b] [Invertible (a * b)] :
    ⅟ (a * b) = ⅟ b * ⅟ a :=
  invOf_eq_right_inv (by 

Proof state:
α : Type u
inst✝³ : Monoid α
a b : α
inst✝² : Invertible a
inst✝¹ : Invertible b
inst✝ : Invertible (a * b)
⊢ a * b * (⅟b * ⅟a) = 1

Next tactic:
simp [← mul_assoc]
variable (c) in
theorem mul_right_inj_of_invertible : a * c = b * c ↔ a = b :=
  ⟨fun h => by 

Proof state:
α : Type u
inst✝¹ : Monoid α
a b c : α
inst✝ : Invertible c
h : a * c = b * c
⊢ a = b

Next tactic:
simpa using congr_arg (· * ⅟c) h
variable (c) in
theorem mul_left_inj_of_invertible : c * a = c * b ↔ a = b :=
  ⟨fun h => by 

Proof state:
α : Type u
inst✝¹ : Monoid α
a b c : α
inst✝ : Invertible c
h : c * a = c * b
⊢ a = b

Next tactic:
simpa using congr_arg (⅟c * ·) h
theorem invOf_mul_eq_iff_eq_mul_left : ⅟c * a = b ↔ a = c * b := by
  

Proof state:
α : Type u
inst✝¹ : Monoid α
a b c : α
inst✝ : Invertible c
⊢ ⅟c * a = b ↔ a = c * b

Next tactic:
rw [← mul_left_inj_of_invertible (c := c), mul_invOf_self_assoc]
theorem mul_left_eq_iff_eq_invOf_mul : c * a = b ↔ a = ⅟c * b := by
  

Proof state:
α : Type u
inst✝¹ : Monoid α
a b c : α
inst✝ : Invertible c
⊢ c * a = b ↔ a = ⅟c * b

Next tactic:
rw [← mul_left_inj_of_invertible (c := ⅟c), invOf_mul_self_assoc]
theorem mul_invOf_eq_iff_eq_mul_right : a * ⅟c = b ↔ a = b * c := by
  

Proof state:
α : Type u
inst✝¹ : Monoid α
a b c : α
inst✝ : Invertible c
⊢ a * ⅟c = b ↔ a = b * c

Next tactic:
rw [← mul_right_inj_of_invertible (c := c), mul_invOf_mul_self_cancel]
theorem mul_right_eq_iff_eq_mul_invOf : a * c = b ↔ a = b * ⅟c := by
  

Proof state:
α : Type u
inst✝¹ : Monoid α
a b c : α
inst✝ : Invertible c
⊢ a * c = b ↔ a = b * ⅟c

Next tactic:
rw [← mul_right_inj_of_invertible (c := ⅟c), mul_mul_invOf_self_cancel]
instance M.Path.inhabited (x : P.last.M) {i} [Inhabited (P.drop.B x.head i)] :
    Inhabited (M.Path P x i) :=
  let a := PFunctor.M.head x
  let f := PFunctor.M.children x
  ⟨M.Path.root _ a f
      (PFunctor.M.casesOn' x
        (r := fun _ => PFunctor.M.dest x = ⟨a, f⟩)
        <| by
        

Proof state:
n : ℕ
P : MvPFunctor.{u} (n + 1)
x : PFunctor.M (last P)
i : Fin2 n
inst✝ : Inhabited (B (drop P) (PFunctor.M.head x) i)
a : (last P).A := PFunctor.M.head x
f : PFunctor.B (last P) (PFunctor.M.head x) → PFunctor.M (last P) := PFunctor.M.children x
⊢ ∀ (a_1 : (last P).A) (f_1 : PFunctor.B (last P) a_1 → PFunctor.M (last P)),
    (fun x_1 => PFunctor.M.dest x = { fst := a, snd := f }) (PFunctor.M.mk { fst := a_1, snd := f_1 })

Next tactic:
intros
instance M.Path.inhabited (x : P.last.M) {i} [Inhabited (P.drop.B x.head i)] :
    Inhabited (M.Path P x i) :=
  let a := PFunctor.M.head x
  let f := PFunctor.M.children x
  ⟨M.Path.root _ a f
      (PFunctor.M.casesOn' x
        (r := fun _ => PFunctor.M.dest x = ⟨a, f⟩)
        <| by
        intros; 

Proof state:
n : ℕ
P : MvPFunctor.{u} (n + 1)
x : PFunctor.M (last P)
i : Fin2 n
inst✝ : Inhabited (B (drop P) (PFunctor.M.head x) i)
a : (last P).A := PFunctor.M.head x
f : PFunctor.B (last P) (PFunctor.M.head x) → PFunctor.M (last P) := PFunctor.M.children x
a✝ : (last P).A
f✝ : PFunctor.B (last P) a✝ → PFunctor.M (last P)
⊢ PFunctor.M.dest x = { fst := a, snd := f }

Next tactic:
simp [PFunctor.M.dest_mk, PFunctor.M.children_mk]
instance M.Path.inhabited (x : P.last.M) {i} [Inhabited (P.drop.B x.head i)] :
    Inhabited (M.Path P x i) :=
  let a := PFunctor.M.head x
  let f := PFunctor.M.children x
  ⟨M.Path.root _ a f
      (PFunctor.M.casesOn' x
        (r := fun _ => PFunctor.M.dest x = ⟨a, f⟩)
        <| by
        intros; simp [PFunctor.M.dest_mk, PFunctor.M.children_mk]; 

Proof state:
n : ℕ
P : MvPFunctor.{u} (n + 1)
x : PFunctor.M (last P)
i : Fin2 n
inst✝ : Inhabited (B (drop P) (PFunctor.M.head x) i)
a : (last P).A := PFunctor.M.head x
f : PFunctor.B (last P) (PFunctor.M.head x) → PFunctor.M (last P) := PFunctor.M.children x
a✝ : (last P).A
f✝ : PFunctor.B (last P) a✝ → PFunctor.M (last P)
⊢ PFunctor.M.dest x = { fst := PFunctor.M.head x, snd := PFunctor.M.children x }

Next tactic:
rfl
instance mvfunctorM : MvFunctor P.M := by 

Proof state:
n : ℕ
P : MvPFunctor.{u} (n + 1)
⊢ MvFunctor (M P)

Next tactic:
delta M
instance mvfunctorM : MvFunctor P.M := by delta M; 

Proof state:
n : ℕ
P : MvPFunctor.{u} (n + 1)
⊢ MvFunctor fun α => ↑(mp P) α

Next tactic:
infer_instance
/-- Using corecursion, construct the contents of an M-type -/
def M.corecContents {α : TypeVec.{u} n}
    {β : Type u}
    (g₀ : β → P.A)
    (g₁ : ∀ b : β, P.drop.B (g₀ b) ⟹ α)
    (g₂ : ∀ b : β, P.last.B (g₀ b) → β)
    (x : _)
    (b : β)
    (h: x = M.corecShape P g₀ g₂ b) :
    M.Path P x ⟹ α
  | _, M.Path.root x a f h' i c =>
    have : a = g₀ b := by
      

Proof state:
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
β : Type u
g₀ : β → P.A
g₁ : (b : β) → B (drop P) (g₀ b) ⟹ α
g₂ : (b : β) → PFunctor.B (last P) (g₀ b) → β
x✝ : PFunctor.M (last P)
b : β
x : PFunctor.M (last P)
i : Fin2 n
a : P.A
f : PFunctor.B (last P) a → PFunctor.M (last P)
h' : PFunctor.M.dest x = { fst := a, snd := f }
c : B (drop P) a i
h : x = corecShape P g₀ g₂ b
⊢ a = g₀ b

Next tactic:
rw [h, M.corecShape, PFunctor.M.dest_corec] at h'
/-- Using corecursion, construct the contents of an M-type -/
def M.corecContents {α : TypeVec.{u} n}
    {β : Type u}
    (g₀ : β → P.A)
    (g₁ : ∀ b : β, P.drop.B (g₀ b) ⟹ α)
    (g₂ : ∀ b : β, P.last.B (g₀ b) → β)
    (x : _)
    (b : β)
    (h: x = M.corecShape P g₀ g₂ b) :
    M.Path P x ⟹ α
  | _, M.Path.root x a f h' i c =>
    have : a = g₀ b := by
      rw [h, M.corecShape, PFunctor.M.dest_corec] at h'
      

Proof state:
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
β : Type u
g₀ : β → P.A
g₁ : (b : β) → B (drop P) (g₀ b) ⟹ α
g₂ : (b : β) → PFunctor.B (last P) (g₀ b) → β
x✝ : PFunctor.M (last P)
b : β
x : PFunctor.M (last P)
i : Fin2 n
a : P.A
f : PFunctor.B (last P) a → PFunctor.M (last P)
h' :
  PFunctor.map (last P) (PFunctor.M.corec fun b => { fst := g₀ b, snd := g₂ b }) { fst := g₀ b, snd := g₂ b } =
    { fst := a, snd := f }
c : B (drop P) a i
h : x = corecShape P g₀ g₂ b
⊢ a = g₀ b

Next tactic:
cases h'
/-- Using corecursion, construct the contents of an M-type -/
def M.corecContents {α : TypeVec.{u} n}
    {β : Type u}
    (g₀ : β → P.A)
    (g₁ : ∀ b : β, P.drop.B (g₀ b) ⟹ α)
    (g₂ : ∀ b : β, P.last.B (g₀ b) → β)
    (x : _)
    (b : β)
    (h: x = M.corecShape P g₀ g₂ b) :
    M.Path P x ⟹ α
  | _, M.Path.root x a f h' i c =>
    have : a = g₀ b := by
      rw [h, M.corecShape, PFunctor.M.dest_corec] at h'
      cases h'
      

Proof state:
case refl
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
β : Type u
g₀ : β → P.A
g₁ : (b : β) → B (drop P) (g₀ b) ⟹ α
g₂ : (b : β) → PFunctor.B (last P) (g₀ b) → β
x✝ : PFunctor.M (last P)
b : β
x : PFunctor.M (last P)
i : Fin2 n
h : x = corecShape P g₀ g₂ b
c : B (drop P) (g₀ b) i
⊢ g₀ b = g₀ b

Next tactic:
rfl
/-- Using corecursion, construct the contents of an M-type -/
def M.corecContents {α : TypeVec.{u} n}
    {β : Type u}
    (g₀ : β → P.A)
    (g₁ : ∀ b : β, P.drop.B (g₀ b) ⟹ α)
    (g₂ : ∀ b : β, P.last.B (g₀ b) → β)
    (x : _)
    (b : β)
    (h: x = M.corecShape P g₀ g₂ b) :
    M.Path P x ⟹ α
  | _, M.Path.root x a f h' i c =>
    have : a = g₀ b := by
      rw [h, M.corecShape, PFunctor.M.dest_corec] at h'
      cases h'
      rfl
    g₁ b i (P.castDropB this i c)
  | _, M.Path.child x a f h' j i c =>
    have h₀ : a = g₀ b := by
      

Proof state:
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
β : Type u
g₀ : β → P.A
g₁ : (b : β) → B (drop P) (g₀ b) ⟹ α
g₂ : (b : β) → PFunctor.B (last P) (g₀ b) → β
x✝ : PFunctor.M (last P)
b : β
x : PFunctor.M (last P)
i : Fin2 n
a : P.A
f : PFunctor.B (last P) a → PFunctor.M (last P)
h' : PFunctor.M.dest x = { fst := a, snd := f }
j : PFunctor.B (last P) a
c : Path P (f j) i
h : x = corecShape P g₀ g₂ b
⊢ a = g₀ b

Next tactic:
rw [h, M.corecShape, PFunctor.M.dest_corec] at h'
/-- Using corecursion, construct the contents of an M-type -/
def M.corecContents {α : TypeVec.{u} n}
    {β : Type u}
    (g₀ : β → P.A)
    (g₁ : ∀ b : β, P.drop.B (g₀ b) ⟹ α)
    (g₂ : ∀ b : β, P.last.B (g₀ b) → β)
    (x : _)
    (b : β)
    (h: x = M.corecShape P g₀ g₂ b) :
    M.Path P x ⟹ α
  | _, M.Path.root x a f h' i c =>
    have : a = g₀ b := by
      rw [h, M.corecShape, PFunctor.M.dest_corec] at h'
      cases h'
      rfl
    g₁ b i (P.castDropB this i c)
  | _, M.Path.child x a f h' j i c =>
    have h₀ : a = g₀ b := by
      rw [h, M.corecShape, PFunctor.M.dest_corec] at h'
      

Proof state:
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
β : Type u
g₀ : β → P.A
g₁ : (b : β) → B (drop P) (g₀ b) ⟹ α
g₂ : (b : β) → PFunctor.B (last P) (g₀ b) → β
x✝ : PFunctor.M (last P)
b : β
x : PFunctor.M (last P)
i : Fin2 n
a : P.A
f : PFunctor.B (last P) a → PFunctor.M (last P)
h' :
  PFunctor.map (last P) (PFunctor.M.corec fun b => { fst := g₀ b, snd := g₂ b }) { fst := g₀ b, snd := g₂ b } =
    { fst := a, snd := f }
j : PFunctor.B (last P) a
c : Path P (f j) i
h : x = corecShape P g₀ g₂ b
⊢ a = g₀ b

Next tactic:
cases h'
/-- Using corecursion, construct the contents of an M-type -/
def M.corecContents {α : TypeVec.{u} n}
    {β : Type u}
    (g₀ : β → P.A)
    (g₁ : ∀ b : β, P.drop.B (g₀ b) ⟹ α)
    (g₂ : ∀ b : β, P.last.B (g₀ b) → β)
    (x : _)
    (b : β)
    (h: x = M.corecShape P g₀ g₂ b) :
    M.Path P x ⟹ α
  | _, M.Path.root x a f h' i c =>
    have : a = g₀ b := by
      rw [h, M.corecShape, PFunctor.M.dest_corec] at h'
      cases h'
      rfl
    g₁ b i (P.castDropB this i c)
  | _, M.Path.child x a f h' j i c =>
    have h₀ : a = g₀ b := by
      rw [h, M.corecShape, PFunctor.M.dest_corec] at h'
      cases h'
      

Proof state:
case refl
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
β : Type u
g₀ : β → P.A
g₁ : (b : β) → B (drop P) (g₀ b) ⟹ α
g₂ : (b : β) → PFunctor.B (last P) (g₀ b) → β
x✝ : PFunctor.M (last P)
b : β
x : PFunctor.M (last P)
i : Fin2 n
h : x = corecShape P g₀ g₂ b
j : PFunctor.B (last P) (g₀ b)
c : Path P (((PFunctor.M.corec fun b => { fst := g₀ b, snd := g₂ b }) ∘ g₂ b) j) i
⊢ g₀ b = g₀ b

Next tactic:
rfl
/-- Using corecursion, construct the contents of an M-type -/
def M.corecContents {α : TypeVec.{u} n}
    {β : Type u}
    (g₀ : β → P.A)
    (g₁ : ∀ b : β, P.drop.B (g₀ b) ⟹ α)
    (g₂ : ∀ b : β, P.last.B (g₀ b) → β)
    (x : _)
    (b : β)
    (h: x = M.corecShape P g₀ g₂ b) :
    M.Path P x ⟹ α
  | _, M.Path.root x a f h' i c =>
    have : a = g₀ b := by
      rw [h, M.corecShape, PFunctor.M.dest_corec] at h'
      cases h'
      rfl
    g₁ b i (P.castDropB this i c)
  | _, M.Path.child x a f h' j i c =>
    have h₀ : a = g₀ b := by
      rw [h, M.corecShape, PFunctor.M.dest_corec] at h'
      cases h'
      rfl
    have h₁ : f j = M.corecShape P g₀ g₂ (g₂ b (castLastB P h₀ j)) := by
      

Proof state:
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
β : Type u
g₀ : β → P.A
g₁ : (b : β) → B (drop P) (g₀ b) ⟹ α
g₂ : (b : β) → PFunctor.B (last P) (g₀ b) → β
x✝ : PFunctor.M (last P)
b : β
x : PFunctor.M (last P)
i : Fin2 n
a : P.A
f : PFunctor.B (last P) a → PFunctor.M (last P)
h' : PFunctor.M.dest x = { fst := a, snd := f }
j : PFunctor.B (last P) a
c : Path P (f j) i
h : x = corecShape P g₀ g₂ b
h₀ : a = g₀ b
⊢ f j = corecShape P g₀ g₂ (g₂ b (castLastB P h₀ j))

Next tactic:
rw [h, M.corecShape, PFunctor.M.dest_corec] at h'
/-- Using corecursion, construct the contents of an M-type -/
def M.corecContents {α : TypeVec.{u} n}
    {β : Type u}
    (g₀ : β → P.A)
    (g₁ : ∀ b : β, P.drop.B (g₀ b) ⟹ α)
    (g₂ : ∀ b : β, P.last.B (g₀ b) → β)
    (x : _)
    (b : β)
    (h: x = M.corecShape P g₀ g₂ b) :
    M.Path P x ⟹ α
  | _, M.Path.root x a f h' i c =>
    have : a = g₀ b := by
      rw [h, M.corecShape, PFunctor.M.dest_corec] at h'
      cases h'
      rfl
    g₁ b i (P.castDropB this i c)
  | _, M.Path.child x a f h' j i c =>
    have h₀ : a = g₀ b := by
      rw [h, M.corecShape, PFunctor.M.dest_corec] at h'
      cases h'
      rfl
    have h₁ : f j = M.corecShape P g₀ g₂ (g₂ b (castLastB P h₀ j)) := by
      rw [h, M.corecShape, PFunctor.M.dest_corec] at h'
      

Proof state:
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
β : Type u
g₀ : β → P.A
g₁ : (b : β) → B (drop P) (g₀ b) ⟹ α
g₂ : (b : β) → PFunctor.B (last P) (g₀ b) → β
x✝ : PFunctor.M (last P)
b : β
x : PFunctor.M (last P)
i : Fin2 n
a : P.A
f : PFunctor.B (last P) a → PFunctor.M (last P)
h' :
  PFunctor.map (last P) (PFunctor.M.corec fun b => { fst := g₀ b, snd := g₂ b }) { fst := g₀ b, snd := g₂ b } =
    { fst := a, snd := f }
j : PFunctor.B (last P) a
c : Path P (f j) i
h : x = corecShape P g₀ g₂ b
h₀ : a = g₀ b
⊢ f j = corecShape P g₀ g₂ (g₂ b (castLastB P h₀ j))

Next tactic:
cases h'
/-- Using corecursion, construct the contents of an M-type -/
def M.corecContents {α : TypeVec.{u} n}
    {β : Type u}
    (g₀ : β → P.A)
    (g₁ : ∀ b : β, P.drop.B (g₀ b) ⟹ α)
    (g₂ : ∀ b : β, P.last.B (g₀ b) → β)
    (x : _)
    (b : β)
    (h: x = M.corecShape P g₀ g₂ b) :
    M.Path P x ⟹ α
  | _, M.Path.root x a f h' i c =>
    have : a = g₀ b := by
      rw [h, M.corecShape, PFunctor.M.dest_corec] at h'
      cases h'
      rfl
    g₁ b i (P.castDropB this i c)
  | _, M.Path.child x a f h' j i c =>
    have h₀ : a = g₀ b := by
      rw [h, M.corecShape, PFunctor.M.dest_corec] at h'
      cases h'
      rfl
    have h₁ : f j = M.corecShape P g₀ g₂ (g₂ b (castLastB P h₀ j)) := by
      rw [h, M.corecShape, PFunctor.M.dest_corec] at h'
      cases h'
      

Proof state:
case refl
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
β : Type u
g₀ : β → P.A
g₁ : (b : β) → B (drop P) (g₀ b) ⟹ α
g₂ : (b : β) → PFunctor.B (last P) (g₀ b) → β
x✝ : PFunctor.M (last P)
b : β
x : PFunctor.M (last P)
i : Fin2 n
h : x = corecShape P g₀ g₂ b
j : PFunctor.B (last P) (g₀ b)
h₀ : g₀ b = g₀ b
c : Path P (((PFunctor.M.corec fun b => { fst := g₀ b, snd := g₂ b }) ∘ g₂ b) j) i
⊢ ((PFunctor.M.corec fun b => { fst := g₀ b, snd := g₂ b }) ∘ g₂ b) j = corecShape P g₀ g₂ (g₂ b (castLastB P h₀ j))

Next tactic:
rfl
theorem M.dest'_eq_dest' {α : TypeVec n} {x : P.last.M} {a₁ : P.A}
    {f₁ : P.last.B a₁ → P.last.M} (h₁ : PFunctor.M.dest x = ⟨a₁, f₁⟩) {a₂ : P.A}
    {f₂ : P.last.B a₂ → P.last.M} (h₂ : PFunctor.M.dest x = ⟨a₂, f₂⟩) (f' : M.Path P x ⟹ α) :
    M.dest' P h₁ f' = M.dest' P h₂ f' := by 

Proof state:
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
x : PFunctor.M (last P)
a₁ : P.A
f₁ : PFunctor.B (last P) a₁ → PFunctor.M (last P)
h₁ : PFunctor.M.dest x = { fst := a₁, snd := f₁ }
a₂ : P.A
f₂ : PFunctor.B (last P) a₂ → PFunctor.M (last P)
h₂ : PFunctor.M.dest x = { fst := a₂, snd := f₂ }
f' : Path P x ⟹ α
⊢ dest' P h₁ f' = dest' P h₂ f'

Next tactic:
cases h₁.symm.trans h₂
theorem M.dest'_eq_dest' {α : TypeVec n} {x : P.last.M} {a₁ : P.A}
    {f₁ : P.last.B a₁ → P.last.M} (h₁ : PFunctor.M.dest x = ⟨a₁, f₁⟩) {a₂ : P.A}
    {f₂ : P.last.B a₂ → P.last.M} (h₂ : PFunctor.M.dest x = ⟨a₂, f₂⟩) (f' : M.Path P x ⟹ α) :
    M.dest' P h₁ f' = M.dest' P h₂ f' := by cases h₁.symm.trans h₂; 

Proof state:
case refl
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
x : PFunctor.M (last P)
a₁ : P.A
f₁ : PFunctor.B (last P) a₁ → PFunctor.M (last P)
h₁ : PFunctor.M.dest x = { fst := a₁, snd := f₁ }
f' : Path P x ⟹ α
h₂ : PFunctor.M.dest x = { fst := a₁, snd := f₁ }
⊢ dest' P h₁ f' = dest' P h₂ f'

Next tactic:
rfl
theorem M.dest_corec {α : TypeVec n} {β : Type u} (g : β → P (α.append1 β)) (x : β) :
    M.dest P (M.corec P g x) = appendFun id (M.corec P g) <$$> g x := by
  

Proof state:
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
β : Type u
g : β → ↑P (α ::: β)
x : β
⊢ dest P (corec P g x) = (TypeVec.id ::: corec P g) <$$> g x

Next tactic:
trans
theorem M.dest_corec {α : TypeVec n} {β : Type u} (g : β → P (α.append1 β)) (x : β) :
    M.dest P (M.corec P g x) = appendFun id (M.corec P g) <$$> g x := by
  trans
  

Proof state:
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
β : Type u
g : β → ↑P (α ::: β)
x : β
⊢ dest P (corec P g x) = ?m.39491
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
β : Type u
g : β → ↑P (α ::: β)
x : β
⊢ ?m.39491 = (TypeVec.id ::: corec P g) <$$> g x
n : ℕ P : MvPFunctor.{u} (n + 1) α : TypeVec.{u} n β : Type u g : β → ↑P (α ::: β) x : β ⊢ ↑P (α ::: M P α)

Next tactic:
apply M.dest_corec'
theorem M.dest_corec {α : TypeVec n} {β : Type u} (g : β → P (α.append1 β)) (x : β) :
    M.dest P (M.corec P g x) = appendFun id (M.corec P g) <$$> g x := by
  trans
  apply M.dest_corec'
  

Proof state:
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
β : Type u
g : β → ↑P (α ::: β)
x : β
⊢ { fst := (g x).fst,
      snd :=
        splitFun (dropFun (g x).snd)
          ((corec' P (fun b => (g b).fst) (fun b => dropFun (g b).snd) fun b => lastFun (g b).snd) ∘
            lastFun (g x).snd) } =
    (TypeVec.id ::: corec P g) <$$> g x

Next tactic:
cases' g x with a f
theorem M.dest_corec {α : TypeVec n} {β : Type u} (g : β → P (α.append1 β)) (x : β) :
    M.dest P (M.corec P g x) = appendFun id (M.corec P g) <$$> g x := by
  trans
  apply M.dest_corec'
  cases' g x with a f; 

Proof state:
case mk
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
β : Type u
g : β → ↑P (α ::: β)
x : β
a : P.A
f : B P a ⟹ α ::: β
⊢ { fst := { fst := a, snd := f }.fst,
      snd :=
        splitFun (dropFun { fst := a, snd := f }.snd)
          ((corec' P (fun b => (g b).fst) (fun b => dropFun (g b).snd) fun b => lastFun (g b).snd) ∘
            lastFun { fst := a, snd := f }.snd) } =
    (TypeVec.id ::: corec P g) <$$> { fst := a, snd := f }

Next tactic:
dsimp
theorem M.dest_corec {α : TypeVec n} {β : Type u} (g : β → P (α.append1 β)) (x : β) :
    M.dest P (M.corec P g x) = appendFun id (M.corec P g) <$$> g x := by
  trans
  apply M.dest_corec'
  cases' g x with a f; dsimp
  

Proof state:
case mk
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
β : Type u
g : β → ↑P (α ::: β)
x : β
a : P.A
f : B P a ⟹ α ::: β
⊢ { fst := a,
      snd :=
        splitFun (dropFun f)
          ((corec' P (fun b => (g b).fst) (fun b => dropFun (g b).snd) fun b => lastFun (g b).snd) ∘ lastFun f) } =
    (TypeVec.id ::: corec P g) <$$> { fst := a, snd := f }

Next tactic:
rw [MvPFunctor.map_eq]
theorem M.dest_corec {α : TypeVec n} {β : Type u} (g : β → P (α.append1 β)) (x : β) :
    M.dest P (M.corec P g x) = appendFun id (M.corec P g) <$$> g x := by
  trans
  apply M.dest_corec'
  cases' g x with a f; dsimp
  rw [MvPFunctor.map_eq]; 

Proof state:
case mk
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
β : Type u
g : β → ↑P (α ::: β)
x : β
a : P.A
f : B P a ⟹ α ::: β
⊢ { fst := a,
      snd :=
        splitFun (dropFun f)
          ((corec' P (fun b => (g b).fst) (fun b => dropFun (g b).snd) fun b => lastFun (g b).snd) ∘ lastFun f) } =
    { fst := a, snd := (TypeVec.id ::: corec P g) ⊚ f }

Next tactic:
congr
theorem M.dest_corec {α : TypeVec n} {β : Type u} (g : β → P (α.append1 β)) (x : β) :
    M.dest P (M.corec P g x) = appendFun id (M.corec P g) <$$> g x := by
  trans
  apply M.dest_corec'
  cases' g x with a f; dsimp
  rw [MvPFunctor.map_eq]; congr
  

Proof state:
case mk.e_snd
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
β : Type u
g : β → ↑P (α ::: β)
x : β
a : P.A
f : B P a ⟹ α ::: β
⊢ splitFun (dropFun f)
      ((corec' P (fun b => (g b).fst) (fun b => dropFun (g b).snd) fun b => lastFun (g b).snd) ∘ lastFun f) =
    (TypeVec.id ::: corec P g) ⊚ f

Next tactic:
conv =>
    rhs
    rw [← split_dropFun_lastFun f, appendFun_comp_splitFun]
theorem M.dest_corec {α : TypeVec n} {β : Type u} (g : β → P (α.append1 β)) (x : β) :
    M.dest P (M.corec P g x) = appendFun id (M.corec P g) <$$> g x := by
  trans
  apply M.dest_corec'
  cases' g x with a f; dsimp
  rw [MvPFunctor.map_eq]; congr
  conv =>
    

Proof state:
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
β : Type u
g : β → ↑P (α ::: β)
x : β
a : P.A
f : B P a ⟹ α ::: β
| splitFun (dropFun f)
      ((corec' P (fun b => (g b).fst) (fun b => dropFun (g b).snd) fun b => lastFun (g b).snd) ∘ lastFun f) =
    (TypeVec.id ::: corec P g) ⊚ f

Next tactic:
rhs
    rw [← split_dropFun_lastFun f, appendFun_comp_splitFun]
theorem M.dest_corec {α : TypeVec n} {β : Type u} (g : β → P (α.append1 β)) (x : β) :
    M.dest P (M.corec P g x) = appendFun id (M.corec P g) <$$> g x := by
  trans
  apply M.dest_corec'
  cases' g x with a f; dsimp
  rw [MvPFunctor.map_eq]; congr
  conv =>
    

Proof state:
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
β : Type u
g : β → ↑P (α ::: β)
x : β
a : P.A
f : B P a ⟹ α ::: β
| splitFun (dropFun f)
      ((corec' P (fun b => (g b).fst) (fun b => dropFun (g b).snd) fun b => lastFun (g b).snd) ∘ lastFun f) =
    (TypeVec.id ::: corec P g) ⊚ f

Next tactic:
rhs
theorem M.dest_corec {α : TypeVec n} {β : Type u} (g : β → P (α.append1 β)) (x : β) :
    M.dest P (M.corec P g x) = appendFun id (M.corec P g) <$$> g x := by
  trans
  apply M.dest_corec'
  cases' g x with a f; dsimp
  rw [MvPFunctor.map_eq]; congr
  conv =>
    rhs
    

Proof state:
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
β : Type u
g : β → ↑P (α ::: β)
x : β
a : P.A
f : B P a ⟹ α ::: β
| (TypeVec.id ::: corec P g) ⊚ f

Next tactic:
rw [← split_dropFun_lastFun f, appendFun_comp_splitFun]
theorem M.bisim_lemma {α : TypeVec n} {a₁ : (mp P).A} {f₁ : (mp P).B a₁ ⟹ α} {a' : P.A}
    {f' : (P.B a').drop ⟹ α} {f₁' : (P.B a').last → M P α}
    (e₁ : M.dest P ⟨a₁, f₁⟩ = ⟨a', splitFun f' f₁'⟩) :
    ∃ (g₁' : _)(e₁' : PFunctor.M.dest a₁ = ⟨a', g₁'⟩),
      f' = M.pathDestLeft P e₁' f₁ ∧
        f₁' = fun x : (last P).B a' => ⟨g₁' x, M.pathDestRight P e₁' f₁ x⟩ := by
  

Proof state:
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
a₁ : (mp P).A
f₁ : B (mp P) a₁ ⟹ α
a' : P.A
f' : TypeVec.drop (B P a') ⟹ α
f₁' : TypeVec.last (B P a') → M P α
e₁ : dest P { fst := a₁, snd := f₁ } = { fst := a', snd := splitFun f' f₁' }
⊢ ∃ g₁',
    ∃ (e₁' : PFunctor.M.dest a₁ = { fst := a', snd := g₁' }),
      f' = pathDestLeft P e₁' f₁ ∧ f₁' = fun x => { fst := g₁' x, snd := pathDestRight P e₁' f₁ x }

Next tactic:
generalize ef : @splitFun n _ (append1 α (M P α)) f' f₁' = ff at e₁
theorem M.bisim_lemma {α : TypeVec n} {a₁ : (mp P).A} {f₁ : (mp P).B a₁ ⟹ α} {a' : P.A}
    {f' : (P.B a').drop ⟹ α} {f₁' : (P.B a').last → M P α}
    (e₁ : M.dest P ⟨a₁, f₁⟩ = ⟨a', splitFun f' f₁'⟩) :
    ∃ (g₁' : _)(e₁' : PFunctor.M.dest a₁ = ⟨a', g₁'⟩),
      f' = M.pathDestLeft P e₁' f₁ ∧
        f₁' = fun x : (last P).B a' => ⟨g₁' x, M.pathDestRight P e₁' f₁ x⟩ := by
  generalize ef : @splitFun n _ (append1 α (M P α)) f' f₁' = ff at e₁
  

Proof state:
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
a₁ : (mp P).A
f₁ : B (mp P) a₁ ⟹ α
a' : P.A
f' : TypeVec.drop (B P a') ⟹ α
f₁' : TypeVec.last (B P a') → M P α
ff : B P a' ⟹ α ::: M P α
ef : splitFun f' f₁' = ff
e₁ : dest P { fst := a₁, snd := f₁ } = { fst := a', snd := ff }
⊢ ∃ g₁',
    ∃ (e₁' : PFunctor.M.dest a₁ = { fst := a', snd := g₁' }),
      f' = pathDestLeft P e₁' f₁ ∧ f₁' = fun x => { fst := g₁' x, snd := pathDestRight P e₁' f₁ x }

Next tactic:
let he₁' := PFunctor.M.dest a₁