l3lab/ntp-mathlib huggingface dataset:
theorem M.bisim {α : TypeVec n} (R : P.M α → P.M α → Prop)
    (h :
      ∀ x y,
        R x y →
          ∃ a f f₁ f₂,
            M.dest P x = ⟨a, splitFun f f₁⟩ ∧
              M.dest P y = ⟨a, splitFun f f₂⟩ ∧ ∀ i, R (f₁ i) (f₂ i))
    (x y) (r : R x y) : x = y := by
  cases' x with a₁ f₁
  cases' y with a₂ f₂
  dsimp [mp] at *
  have : a₁ = a₂ := by
    refine'
      PFunctor.M.bisim (fun a₁ a₂ => ∃ x y, R x y ∧ x.1 = a₁ ∧ y.1 = a₂) _ _ _
        ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rintro _ _ ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h'⟩
    rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
    rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', _, rfl⟩
    rw [e₁', e₂']
    exact ⟨_, _, _, rfl, rfl, fun b => ⟨_, _, h' b, rfl, rfl⟩⟩
  subst this
  congr with (i p)
  

Proof state:
case mk.mk.e_snd.a.h
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
f₁ f₂ : B (mp P) a₁ ⟹ α
r : R { fst := a₁, snd := f₁ } { fst := a₁, snd := f₂ }
i : Fin2 n
p : B (mp P) a₁ i
⊢ f₁ i p = f₂ i p

Next tactic:
induction' p with x a f h' i c x a f h' i c p IH
theorem M.bisim {α : TypeVec n} (R : P.M α → P.M α → Prop)
    (h :
      ∀ x y,
        R x y →
          ∃ a f f₁ f₂,
            M.dest P x = ⟨a, splitFun f f₁⟩ ∧
              M.dest P y = ⟨a, splitFun f f₂⟩ ∧ ∀ i, R (f₁ i) (f₂ i))
    (x y) (r : R x y) : x = y := by
  cases' x with a₁ f₁
  cases' y with a₂ f₂
  dsimp [mp] at *
  have : a₁ = a₂ := by
    refine'
      PFunctor.M.bisim (fun a₁ a₂ => ∃ x y, R x y ∧ x.1 = a₁ ∧ y.1 = a₂) _ _ _
        ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rintro _ _ ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h'⟩
    rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
    rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', _, rfl⟩
    rw [e₁', e₂']
    exact ⟨_, _, _, rfl, rfl, fun b => ⟨_, _, h' b, rfl, rfl⟩⟩
  subst this
  congr with (i p)
  induction' p with x a f h' i c x a f h' i c p IH <;>
    

Proof state:
case mk.mk.e_snd.a.h.root
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
i✝ : Fin2 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 }
i : Fin2 n
c : B (drop P) a i
f₁ f₂ : B (mp P) x ⟹ α
r : R { fst := x, snd := f₁ } { fst := x, snd := f₂ }
⊢ f₁ i (Path.root x a f h' i c) = f₂ i (Path.root x a f h' i c)

Next tactic:
try
      rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h''⟩
      rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
      rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', e₃, rfl⟩
      cases h'.symm.trans e₁'
      cases h'.symm.trans e₂'
theorem M.bisim {α : TypeVec n} (R : P.M α → P.M α → Prop)
    (h :
      ∀ x y,
        R x y →
          ∃ a f f₁ f₂,
            M.dest P x = ⟨a, splitFun f f₁⟩ ∧
              M.dest P y = ⟨a, splitFun f f₂⟩ ∧ ∀ i, R (f₁ i) (f₂ i))
    (x y) (r : R x y) : x = y := by
  cases' x with a₁ f₁
  cases' y with a₂ f₂
  dsimp [mp] at *
  have : a₁ = a₂ := by
    refine'
      PFunctor.M.bisim (fun a₁ a₂ => ∃ x y, R x y ∧ x.1 = a₁ ∧ y.1 = a₂) _ _ _
        ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rintro _ _ ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h'⟩
    rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
    rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', _, rfl⟩
    rw [e₁', e₂']
    exact ⟨_, _, _, rfl, rfl, fun b => ⟨_, _, h' b, rfl, rfl⟩⟩
  subst this
  congr with (i p)
  induction' p with x a f h' i c x a f h' i c p IH <;>
    try
      

Proof state:
case mk.mk.e_snd.a.h.root
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
i✝ : Fin2 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 }
i : Fin2 n
c : B (drop P) a i
f₁ f₂ : B (mp P) x ⟹ α
r : R { fst := x, snd := f₁ } { fst := x, snd := f₂ }
⊢ f₁ i (Path.root x a f h' i c) = f₂ i (Path.root x a f h' i c)

Next tactic:
rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h''⟩
theorem M.bisim {α : TypeVec n} (R : P.M α → P.M α → Prop)
    (h :
      ∀ x y,
        R x y →
          ∃ a f f₁ f₂,
            M.dest P x = ⟨a, splitFun f f₁⟩ ∧
              M.dest P y = ⟨a, splitFun f f₂⟩ ∧ ∀ i, R (f₁ i) (f₂ i))
    (x y) (r : R x y) : x = y := by
  cases' x with a₁ f₁
  cases' y with a₂ f₂
  dsimp [mp] at *
  have : a₁ = a₂ := by
    refine'
      PFunctor.M.bisim (fun a₁ a₂ => ∃ x y, R x y ∧ x.1 = a₁ ∧ y.1 = a₂) _ _ _
        ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rintro _ _ ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h'⟩
    rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
    rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', _, rfl⟩
    rw [e₁', e₂']
    exact ⟨_, _, _, rfl, rfl, fun b => ⟨_, _, h' b, rfl, rfl⟩⟩
  subst this
  congr with (i p)
  induction' p with x a f h' i c x a f h' i c p IH <;>
    try
      rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h''⟩
      

Proof state:
case mk.mk.e_snd.a.h.root.intro.intro.intro.intro.intro.intro
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
i✝ : Fin2 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 }
i : Fin2 n
c : B (drop P) a i
f₁ f₂ : B (mp P) x ⟹ α
r : R { fst := x, snd := f₁ } { fst := x, snd := f₂ }
a' : P.A
f' : TypeVec.drop (B P a') ⟹ TypeVec.drop (α ::: M P α)
f₁' f₂' : TypeVec.last (B P a') → TypeVec.last (α ::: M P α)
e₁ : dest P { fst := x, snd := f₁ } = { fst := a', snd := splitFun f' f₁' }
e₂ : dest P { fst := x, snd := f₂ } = { fst := a', snd := splitFun f' f₂' }
h'' : ∀ (i : TypeVec.last (B P a')), R (f₁' i) (f₂' i)
⊢ f₁ i (Path.root x a f h' i c) = f₂ i (Path.root x a f h' i c)

Next tactic:
rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
theorem M.bisim {α : TypeVec n} (R : P.M α → P.M α → Prop)
    (h :
      ∀ x y,
        R x y →
          ∃ a f f₁ f₂,
            M.dest P x = ⟨a, splitFun f f₁⟩ ∧
              M.dest P y = ⟨a, splitFun f f₂⟩ ∧ ∀ i, R (f₁ i) (f₂ i))
    (x y) (r : R x y) : x = y := by
  cases' x with a₁ f₁
  cases' y with a₂ f₂
  dsimp [mp] at *
  have : a₁ = a₂ := by
    refine'
      PFunctor.M.bisim (fun a₁ a₂ => ∃ x y, R x y ∧ x.1 = a₁ ∧ y.1 = a₂) _ _ _
        ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rintro _ _ ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h'⟩
    rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
    rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', _, rfl⟩
    rw [e₁', e₂']
    exact ⟨_, _, _, rfl, rfl, fun b => ⟨_, _, h' b, rfl, rfl⟩⟩
  subst this
  congr with (i p)
  induction' p with x a f h' i c x a f h' i c p IH <;>
    try
      rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h''⟩
      rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
      

Proof state:
case mk.mk.e_snd.a.h.root.intro.intro.intro.intro.intro.intro.intro.intro.intro
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
i✝ : Fin2 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 }
i : Fin2 n
c : B (drop P) a i
f₁ f₂ : B (mp P) x ⟹ α
r : R { fst := x, snd := f₁ } { fst := x, snd := f₂ }
a' : P.A
f₂' : TypeVec.last (B P a') → TypeVec.last (α ::: M P α)
g₁' : PFunctor.B (last P) a' → PFunctor.M (last P)
e₁' : PFunctor.M.dest x = { fst := a', snd := g₁' }
e₂ : dest P { fst := x, snd := f₂ } = { fst := a', snd := splitFun (pathDestLeft P e₁' f₁) f₂' }
h'' : ∀ (i : TypeVec.last (B P a')), R ((fun x_1 => { fst := g₁' x_1, snd := pathDestRight P e₁' f₁ x_1 }) i) (f₂' i)
e₁ :
  dest P { fst := x, snd := f₁ } =
    { fst := a',
      snd := splitFun (pathDestLeft P e₁' f₁) fun x_1 => { fst := g₁' x_1, snd := pathDestRight P e₁' f₁ x_1 } }
⊢ f₁ i (Path.root x a f h' i c) = f₂ i (Path.root x a f h' i c)

Next tactic:
rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', e₃, rfl⟩
theorem M.bisim {α : TypeVec n} (R : P.M α → P.M α → Prop)
    (h :
      ∀ x y,
        R x y →
          ∃ a f f₁ f₂,
            M.dest P x = ⟨a, splitFun f f₁⟩ ∧
              M.dest P y = ⟨a, splitFun f f₂⟩ ∧ ∀ i, R (f₁ i) (f₂ i))
    (x y) (r : R x y) : x = y := by
  cases' x with a₁ f₁
  cases' y with a₂ f₂
  dsimp [mp] at *
  have : a₁ = a₂ := by
    refine'
      PFunctor.M.bisim (fun a₁ a₂ => ∃ x y, R x y ∧ x.1 = a₁ ∧ y.1 = a₂) _ _ _
        ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rintro _ _ ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h'⟩
    rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
    rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', _, rfl⟩
    rw [e₁', e₂']
    exact ⟨_, _, _, rfl, rfl, fun b => ⟨_, _, h' b, rfl, rfl⟩⟩
  subst this
  congr with (i p)
  induction' p with x a f h' i c x a f h' i c p IH <;>
    try
      rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h''⟩
      rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
      rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', e₃, rfl⟩
      

Proof state:
case mk.mk.e_snd.a.h.root.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
i✝ : Fin2 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 }
i : Fin2 n
c : B (drop P) a i
f₁ f₂ : B (mp P) x ⟹ α
r : R { fst := x, snd := f₁ } { fst := x, snd := f₂ }
a' : P.A
g₁' : PFunctor.B (last P) a' → PFunctor.M (last P)
e₁' : PFunctor.M.dest x = { fst := a', snd := g₁' }
e₁ :
  dest P { fst := x, snd := f₁ } =
    { fst := a',
      snd := splitFun (pathDestLeft P e₁' f₁) fun x_1 => { fst := g₁' x_1, snd := pathDestRight P e₁' f₁ x_1 } }
g₂' : PFunctor.B (last P) a' → PFunctor.M (last P)
e₂' : PFunctor.M.dest x = { fst := a', snd := g₂' }
e₃ : pathDestLeft P e₁' f₁ = pathDestLeft P e₂' f₂
e₂ :
  dest P { fst := x, snd := f₂ } =
    { fst := a',
      snd := splitFun (pathDestLeft P e₁' f₁) fun x_1 => { fst := g₂' x_1, snd := pathDestRight P e₂' f₂ x_1 } }
h'' :
  ∀ (i : TypeVec.last (B P a')),
    R ((fun x_1 => { fst := g₁' x_1, snd := pathDestRight P e₁' f₁ x_1 }) i)
      ((fun x_1 => { fst := g₂' x_1, snd := pathDestRight P e₂' f₂ x_1 }) i)
⊢ f₁ i (Path.root x a f h' i c) = f₂ i (Path.root x a f h' i c)

Next tactic:
cases h'.symm.trans e₁'
theorem M.bisim {α : TypeVec n} (R : P.M α → P.M α → Prop)
    (h :
      ∀ x y,
        R x y →
          ∃ a f f₁ f₂,
            M.dest P x = ⟨a, splitFun f f₁⟩ ∧
              M.dest P y = ⟨a, splitFun f f₂⟩ ∧ ∀ i, R (f₁ i) (f₂ i))
    (x y) (r : R x y) : x = y := by
  cases' x with a₁ f₁
  cases' y with a₂ f₂
  dsimp [mp] at *
  have : a₁ = a₂ := by
    refine'
      PFunctor.M.bisim (fun a₁ a₂ => ∃ x y, R x y ∧ x.1 = a₁ ∧ y.1 = a₂) _ _ _
        ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rintro _ _ ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h'⟩
    rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
    rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', _, rfl⟩
    rw [e₁', e₂']
    exact ⟨_, _, _, rfl, rfl, fun b => ⟨_, _, h' b, rfl, rfl⟩⟩
  subst this
  congr with (i p)
  induction' p with x a f h' i c x a f h' i c p IH <;>
    try
      rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h''⟩
      rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
      rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', e₃, rfl⟩
      cases h'.symm.trans e₁'
      

Proof state:
case mk.mk.e_snd.a.h.root.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.refl
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
i✝ : Fin2 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 }
i : Fin2 n
c : B (drop P) a i
f₁ f₂ : B (mp P) x ⟹ α
r : R { fst := x, snd := f₁ } { fst := x, snd := f₂ }
g₂' : PFunctor.B (last P) a → PFunctor.M (last P)
e₂' : PFunctor.M.dest x = { fst := a, snd := g₂' }
e₁' : PFunctor.M.dest x = { fst := a, snd := f }
e₁ :
  dest P { fst := x, snd := f₁ } =
    { fst := a, snd := splitFun (pathDestLeft P e₁' f₁) fun x_1 => { fst := f x_1, snd := pathDestRight P e₁' f₁ x_1 } }
e₃ : pathDestLeft P e₁' f₁ = pathDestLeft P e₂' f₂
e₂ :
  dest P { fst := x, snd := f₂ } =
    { fst := a,
      snd := splitFun (pathDestLeft P e₁' f₁) fun x_1 => { fst := g₂' x_1, snd := pathDestRight P e₂' f₂ x_1 } }
h'' :
  ∀ (i : TypeVec.last (B P a)),
    R ((fun x_1 => { fst := f x_1, snd := pathDestRight P e₁' f₁ x_1 }) i)
      ((fun x_1 => { fst := g₂' x_1, snd := pathDestRight P e₂' f₂ x_1 }) i)
⊢ f₁ i (Path.root x a f h' i c) = f₂ i (Path.root x a f h' i c)

Next tactic:
cases h'.symm.trans e₂'
theorem M.bisim {α : TypeVec n} (R : P.M α → P.M α → Prop)
    (h :
      ∀ x y,
        R x y →
          ∃ a f f₁ f₂,
            M.dest P x = ⟨a, splitFun f f₁⟩ ∧
              M.dest P y = ⟨a, splitFun f f₂⟩ ∧ ∀ i, R (f₁ i) (f₂ i))
    (x y) (r : R x y) : x = y := by
  cases' x with a₁ f₁
  cases' y with a₂ f₂
  dsimp [mp] at *
  have : a₁ = a₂ := by
    refine'
      PFunctor.M.bisim (fun a₁ a₂ => ∃ x y, R x y ∧ x.1 = a₁ ∧ y.1 = a₂) _ _ _
        ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rintro _ _ ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h'⟩
    rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
    rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', _, rfl⟩
    rw [e₁', e₂']
    exact ⟨_, _, _, rfl, rfl, fun b => ⟨_, _, h' b, rfl, rfl⟩⟩
  subst this
  congr with (i p)
  induction' p with x a f h' i c x a f h' i c p IH <;>
    

Proof state:
case mk.mk.e_snd.a.h.child
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
i✝ : Fin2 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 }
i : PFunctor.B (last P) a
c : Fin2 n
p : Path P (f i) c
IH : ∀ (f₁ f₂ : B (mp P) (f i) ⟹ α), R { fst := f i, snd := f₁ } { fst := f i, snd := f₂ } → f₁ c p = f₂ c p
f₁ f₂ : B (mp P) x ⟹ α
r : R { fst := x, snd := f₁ } { fst := x, snd := f₂ }
⊢ f₁ c (Path.child x a f h' i c p) = f₂ c (Path.child x a f h' i c p)

Next tactic:
try
      rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h''⟩
      rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
      rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', e₃, rfl⟩
      cases h'.symm.trans e₁'
      cases h'.symm.trans e₂'
theorem M.bisim {α : TypeVec n} (R : P.M α → P.M α → Prop)
    (h :
      ∀ x y,
        R x y →
          ∃ a f f₁ f₂,
            M.dest P x = ⟨a, splitFun f f₁⟩ ∧
              M.dest P y = ⟨a, splitFun f f₂⟩ ∧ ∀ i, R (f₁ i) (f₂ i))
    (x y) (r : R x y) : x = y := by
  cases' x with a₁ f₁
  cases' y with a₂ f₂
  dsimp [mp] at *
  have : a₁ = a₂ := by
    refine'
      PFunctor.M.bisim (fun a₁ a₂ => ∃ x y, R x y ∧ x.1 = a₁ ∧ y.1 = a₂) _ _ _
        ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rintro _ _ ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h'⟩
    rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
    rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', _, rfl⟩
    rw [e₁', e₂']
    exact ⟨_, _, _, rfl, rfl, fun b => ⟨_, _, h' b, rfl, rfl⟩⟩
  subst this
  congr with (i p)
  induction' p with x a f h' i c x a f h' i c p IH <;>
    try
      

Proof state:
case mk.mk.e_snd.a.h.child
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
i✝ : Fin2 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 }
i : PFunctor.B (last P) a
c : Fin2 n
p : Path P (f i) c
IH : ∀ (f₁ f₂ : B (mp P) (f i) ⟹ α), R { fst := f i, snd := f₁ } { fst := f i, snd := f₂ } → f₁ c p = f₂ c p
f₁ f₂ : B (mp P) x ⟹ α
r : R { fst := x, snd := f₁ } { fst := x, snd := f₂ }
⊢ f₁ c (Path.child x a f h' i c p) = f₂ c (Path.child x a f h' i c p)

Next tactic:
rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h''⟩
theorem M.bisim {α : TypeVec n} (R : P.M α → P.M α → Prop)
    (h :
      ∀ x y,
        R x y →
          ∃ a f f₁ f₂,
            M.dest P x = ⟨a, splitFun f f₁⟩ ∧
              M.dest P y = ⟨a, splitFun f f₂⟩ ∧ ∀ i, R (f₁ i) (f₂ i))
    (x y) (r : R x y) : x = y := by
  cases' x with a₁ f₁
  cases' y with a₂ f₂
  dsimp [mp] at *
  have : a₁ = a₂ := by
    refine'
      PFunctor.M.bisim (fun a₁ a₂ => ∃ x y, R x y ∧ x.1 = a₁ ∧ y.1 = a₂) _ _ _
        ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rintro _ _ ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h'⟩
    rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
    rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', _, rfl⟩
    rw [e₁', e₂']
    exact ⟨_, _, _, rfl, rfl, fun b => ⟨_, _, h' b, rfl, rfl⟩⟩
  subst this
  congr with (i p)
  induction' p with x a f h' i c x a f h' i c p IH <;>
    try
      rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h''⟩
      

Proof state:
case mk.mk.e_snd.a.h.child.intro.intro.intro.intro.intro.intro
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
i✝ : Fin2 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 }
i : PFunctor.B (last P) a
c : Fin2 n
p : Path P (f i) c
IH : ∀ (f₁ f₂ : B (mp P) (f i) ⟹ α), R { fst := f i, snd := f₁ } { fst := f i, snd := f₂ } → f₁ c p = f₂ c p
f₁ f₂ : B (mp P) x ⟹ α
r : R { fst := x, snd := f₁ } { fst := x, snd := f₂ }
a' : P.A
f' : TypeVec.drop (B P a') ⟹ TypeVec.drop (α ::: M P α)
f₁' f₂' : TypeVec.last (B P a') → TypeVec.last (α ::: M P α)
e₁ : dest P { fst := x, snd := f₁ } = { fst := a', snd := splitFun f' f₁' }
e₂ : dest P { fst := x, snd := f₂ } = { fst := a', snd := splitFun f' f₂' }
h'' : ∀ (i : TypeVec.last (B P a')), R (f₁' i) (f₂' i)
⊢ f₁ c (Path.child x a f h' i c p) = f₂ c (Path.child x a f h' i c p)

Next tactic:
rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
theorem M.bisim {α : TypeVec n} (R : P.M α → P.M α → Prop)
    (h :
      ∀ x y,
        R x y →
          ∃ a f f₁ f₂,
            M.dest P x = ⟨a, splitFun f f₁⟩ ∧
              M.dest P y = ⟨a, splitFun f f₂⟩ ∧ ∀ i, R (f₁ i) (f₂ i))
    (x y) (r : R x y) : x = y := by
  cases' x with a₁ f₁
  cases' y with a₂ f₂
  dsimp [mp] at *
  have : a₁ = a₂ := by
    refine'
      PFunctor.M.bisim (fun a₁ a₂ => ∃ x y, R x y ∧ x.1 = a₁ ∧ y.1 = a₂) _ _ _
        ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rintro _ _ ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
    rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h'⟩
    rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
    rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', _, rfl⟩
    rw [e₁', e₂']
    exact ⟨_, _, _, rfl, rfl, fun b => ⟨_, _, h' b, rfl, rfl⟩⟩
  subst this
  congr with (i p)
  induction' p with x a f h' i c x a f h' i c p IH <;>
    try
      rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h''⟩
      rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
      

Proof state:
case mk.mk.e_snd.a.h.child.intro.intro.intro.intro.intro.intro.intro.intro.intro
n : ℕ
P : MvPFunctor.{u} (n + 1)
α : TypeVec.{u} n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
i✝ : Fin2 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 }
i : PFunctor.B (last P) a
c : Fin2 n
p : Path P (f i) c
IH : ∀ (f₁ f₂ : B (mp P) (f i) ⟹ α), R { fst := f i, snd := f₁ } { fst := f i, snd := f₂ } → f₁ c p = f₂ c p
f₁ f₂ : B (mp P) x ⟹ α
r : R { fst := x, snd := f₁ } { fst := x, snd := f₂ }
a' : P.A
f₂' : TypeVec.last (B P a') → TypeVec.last (α ::: M P α)
g₁' : PFunctor.B (last P) a' → PFunctor.M (last P)
e₁' : PFunctor.M.dest x = { fst := a', snd := g₁' }
e₂ : dest P { fst := x, snd := f₂ } = { fst := a', snd := splitFun (pathDestLeft P e₁' f₁) f₂' }
h'' : ∀ (i : TypeVec.last (B P a')), R ((fun x_1 => { fst := g₁' x_1, snd := pathDestRight P e₁' f₁ x_1 }) i) (f₂' i)
e₁ :
  dest P { fst := x, snd := f₁ } =
    { fst := a',
      snd := splitFun (pathDestLeft P e₁' f₁) fun x_1 => { fst := g₁' x_1, snd := pathDestRight P e₁' f₁ x_1 } }
⊢ f₁ c (Path.child x a f h' i c p) = f₂ c (Path.child x a f h' i c p)

Next tactic:
rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', e₃, rfl⟩