l3lab/ntp-mathlib huggingface dataset:
theorem Cofix.bisim_rel (r : Cofix F → Cofix F → Prop)
    (h : ∀ x y, r x y → Quot.mk r <$> Cofix.dest x = Quot.mk r <$> Cofix.dest y) :
    ∀ x y, r x y → x = y := by
  let r' (x y) := x = y ∨ r x y
  intro x y rxy
  apply Cofix.bisim_aux r'
  · intro x
    left
    rfl
  · intro x y r'xy
    cases' r'xy with r'xy r'xy
    · rw [r'xy]
    have : ∀ x y, r x y → r' x y := fun x y h => Or.inr h
    rw [← Quot.factor_mk_eq _ _ this]
    

Proof state:
case h.inr
F : Type u → Type u
inst✝ : Functor F
q : QPF F
r : Cofix F → Cofix F → Prop
h : ∀ (x y : Cofix F), r x y → Quot.mk r <$> dest x = Quot.mk r <$> dest y
r' : Cofix F → Cofix F → Prop := fun x y => x = y ∨ r x y
x✝ y✝ : Cofix F
rxy : r x✝ y✝
x y : Cofix F
r'xy : r x y
this : ∀ (x y : Cofix F), r x y → r' x y
⊢ (Quot.factor (fun x y => r x y) (fun x y => r' x y) this ∘ Quot.mk fun x y => r x y) <$> dest x =
    (Quot.factor (fun x y => r x y) (fun x y => r' x y) this ∘ Quot.mk fun x y => r x y) <$> dest y

Next tactic:
dsimp
theorem Cofix.bisim_rel (r : Cofix F → Cofix F → Prop)
    (h : ∀ x y, r x y → Quot.mk r <$> Cofix.dest x = Quot.mk r <$> Cofix.dest y) :
    ∀ x y, r x y → x = y := by
  let r' (x y) := x = y ∨ r x y
  intro x y rxy
  apply Cofix.bisim_aux r'
  · intro x
    left
    rfl
  · intro x y r'xy
    cases' r'xy with r'xy r'xy
    · rw [r'xy]
    have : ∀ x y, r x y → r' x y := fun x y h => Or.inr h
    rw [← Quot.factor_mk_eq _ _ this]
    dsimp
    

Proof state:
case h.inr
F : Type u → Type u
inst✝ : Functor F
q : QPF F
r : Cofix F → Cofix F → Prop
h : ∀ (x y : Cofix F), r x y → Quot.mk r <$> dest x = Quot.mk r <$> dest y
r' : Cofix F → Cofix F → Prop := fun x y => x = y ∨ r x y
x✝ y✝ : Cofix F
rxy : r x✝ y✝
x y : Cofix F
r'xy : r x y
this : ∀ (x y : Cofix F), r x y → r' x y
⊢ (Quot.factor (fun x y => r x y) (fun x y => x = y ∨ r x y) this ∘ Quot.mk fun x y => r x y) <$> dest x =
    (Quot.factor (fun x y => r x y) (fun x y => x = y ∨ r x y) this ∘ Quot.mk fun x y => r x y) <$> dest y

Next tactic:
rw [@comp_map _ _ q _ _ _ (Quot.mk r), @comp_map _ _ q _ _ _ (Quot.mk r)]
theorem Cofix.bisim_rel (r : Cofix F → Cofix F → Prop)
    (h : ∀ x y, r x y → Quot.mk r <$> Cofix.dest x = Quot.mk r <$> Cofix.dest y) :
    ∀ x y, r x y → x = y := by
  let r' (x y) := x = y ∨ r x y
  intro x y rxy
  apply Cofix.bisim_aux r'
  · intro x
    left
    rfl
  · intro x y r'xy
    cases' r'xy with r'xy r'xy
    · rw [r'xy]
    have : ∀ x y, r x y → r' x y := fun x y h => Or.inr h
    rw [← Quot.factor_mk_eq _ _ this]
    dsimp
    rw [@comp_map _ _ q _ _ _ (Quot.mk r), @comp_map _ _ q _ _ _ (Quot.mk r)]
    

Proof state:
case h.inr
F : Type u → Type u
inst✝ : Functor F
q : QPF F
r : Cofix F → Cofix F → Prop
h : ∀ (x y : Cofix F), r x y → Quot.mk r <$> dest x = Quot.mk r <$> dest y
r' : Cofix F → Cofix F → Prop := fun x y => x = y ∨ r x y
x✝ y✝ : Cofix F
rxy : r x✝ y✝
x y : Cofix F
r'xy : r x y
this : ∀ (x y : Cofix F), r x y → r' x y
⊢ Quot.factor (fun x y => r x y) (fun x y => x = y ∨ r x y) this <$> Quot.mk r <$> dest x =
    Quot.factor (fun x y => r x y) (fun x y => x = y ∨ r x y) this <$> Quot.mk r <$> dest y

Next tactic:
rw [h _ _ r'xy]
theorem Cofix.bisim_rel (r : Cofix F → Cofix F → Prop)
    (h : ∀ x y, r x y → Quot.mk r <$> Cofix.dest x = Quot.mk r <$> Cofix.dest y) :
    ∀ x y, r x y → x = y := by
  let r' (x y) := x = y ∨ r x y
  intro x y rxy
  apply Cofix.bisim_aux r'
  · intro x
    left
    rfl
  · intro x y r'xy
    cases' r'xy with r'xy r'xy
    · rw [r'xy]
    have : ∀ x y, r x y → r' x y := fun x y h => Or.inr h
    rw [← Quot.factor_mk_eq _ _ this]
    dsimp
    rw [@comp_map _ _ q _ _ _ (Quot.mk r), @comp_map _ _ q _ _ _ (Quot.mk r)]
    rw [h _ _ r'xy]
  

Proof state:
case a
F : Type u → Type u
inst✝ : Functor F
q : QPF F
r : Cofix F → Cofix F → Prop
h : ∀ (x y : Cofix F), r x y → Quot.mk r <$> dest x = Quot.mk r <$> dest y
r' : Cofix F → Cofix F → Prop := fun x y => x = y ∨ r x y
x y : Cofix F
rxy : r x y
⊢ r' x y

Next tactic:
right
theorem Cofix.bisim_rel (r : Cofix F → Cofix F → Prop)
    (h : ∀ x y, r x y → Quot.mk r <$> Cofix.dest x = Quot.mk r <$> Cofix.dest y) :
    ∀ x y, r x y → x = y := by
  let r' (x y) := x = y ∨ r x y
  intro x y rxy
  apply Cofix.bisim_aux r'
  · intro x
    left
    rfl
  · intro x y r'xy
    cases' r'xy with r'xy r'xy
    · rw [r'xy]
    have : ∀ x y, r x y → r' x y := fun x y h => Or.inr h
    rw [← Quot.factor_mk_eq _ _ this]
    dsimp
    rw [@comp_map _ _ q _ _ _ (Quot.mk r), @comp_map _ _ q _ _ _ (Quot.mk r)]
    rw [h _ _ r'xy]
  right; 

Proof state:
case a.h
F : Type u → Type u
inst✝ : Functor F
q : QPF F
r : Cofix F → Cofix F → Prop
h : ∀ (x y : Cofix F), r x y → Quot.mk r <$> dest x = Quot.mk r <$> dest y
r' : Cofix F → Cofix F → Prop := fun x y => x = y ∨ r x y
x y : Cofix F
rxy : r x y
⊢ r x y

Next tactic:
exact rxy
theorem Cofix.bisim (r : Cofix F → Cofix F → Prop)
    (h : ∀ x y, r x y → Liftr r (Cofix.dest x) (Cofix.dest y)) : ∀ x y, r x y → x = y := by
  

Proof state:
F : Type u → Type u
inst✝ : Functor F
q : QPF F
r : Cofix F → Cofix F → Prop
h : ∀ (x y : Cofix F), r x y → Liftr r (dest x) (dest y)
⊢ ∀ (x y : Cofix F), r x y → x = y

Next tactic:
apply Cofix.bisim_rel
theorem Cofix.bisim (r : Cofix F → Cofix F → Prop)
    (h : ∀ x y, r x y → Liftr r (Cofix.dest x) (Cofix.dest y)) : ∀ x y, r x y → x = y := by
  apply Cofix.bisim_rel
  

Proof state:
case h
F : Type u → Type u
inst✝ : Functor F
q : QPF F
r : Cofix F → Cofix F → Prop
h : ∀ (x y : Cofix F), r x y → Liftr r (dest x) (dest y)
⊢ ∀ (x y : Cofix F), r x y → (Quot.mk fun x y => r x y) <$> dest x = (Quot.mk fun x y => r x y) <$> dest y

Next tactic:
intro x y rxy
theorem Cofix.bisim (r : Cofix F → Cofix F → Prop)
    (h : ∀ x y, r x y → Liftr r (Cofix.dest x) (Cofix.dest y)) : ∀ x y, r x y → x = y := by
  apply Cofix.bisim_rel
  intro x y rxy
  

Proof state:
case h
F : Type u → Type u
inst✝ : Functor F
q : QPF F
r : Cofix F → Cofix F → Prop
h : ∀ (x y : Cofix F), r x y → Liftr r (dest x) (dest y)
x y : Cofix F
rxy : r x y
⊢ (Quot.mk fun x y => r x y) <$> dest x = (Quot.mk fun x y => r x y) <$> dest y

Next tactic:
rcases (liftr_iff r _ _).mp (h x y rxy) with ⟨a, f₀, f₁, dxeq, dyeq, h'⟩
theorem Cofix.bisim (r : Cofix F → Cofix F → Prop)
    (h : ∀ x y, r x y → Liftr r (Cofix.dest x) (Cofix.dest y)) : ∀ x y, r x y → x = y := by
  apply Cofix.bisim_rel
  intro x y rxy
  rcases (liftr_iff r _ _).mp (h x y rxy) with ⟨a, f₀, f₁, dxeq, dyeq, h'⟩
  

Proof state:
case h.intro.intro.intro.intro.intro
F : Type u → Type u
inst✝ : Functor F
q : QPF F
r : Cofix F → Cofix F → Prop
h : ∀ (x y : Cofix F), r x y → Liftr r (dest x) (dest y)
x y : Cofix F
rxy : r x y
a : (P F).A
f₀ f₁ : PFunctor.B (P F) a → Cofix F
dxeq : dest x = abs { fst := a, snd := f₀ }
dyeq : dest y = abs { fst := a, snd := f₁ }
h' : ∀ (i : PFunctor.B (P F) a), r (f₀ i) (f₁ i)
⊢ (Quot.mk fun x y => r x y) <$> dest x = (Quot.mk fun x y => r x y) <$> dest y

Next tactic:
rw [dxeq, dyeq, ← abs_map, ← abs_map, PFunctor.map_eq, PFunctor.map_eq]
theorem Cofix.bisim (r : Cofix F → Cofix F → Prop)
    (h : ∀ x y, r x y → Liftr r (Cofix.dest x) (Cofix.dest y)) : ∀ x y, r x y → x = y := by
  apply Cofix.bisim_rel
  intro x y rxy
  rcases (liftr_iff r _ _).mp (h x y rxy) with ⟨a, f₀, f₁, dxeq, dyeq, h'⟩
  rw [dxeq, dyeq, ← abs_map, ← abs_map, PFunctor.map_eq, PFunctor.map_eq]
  

Proof state:
case h.intro.intro.intro.intro.intro
F : Type u → Type u
inst✝ : Functor F
q : QPF F
r : Cofix F → Cofix F → Prop
h : ∀ (x y : Cofix F), r x y → Liftr r (dest x) (dest y)
x y : Cofix F
rxy : r x y
a : (P F).A
f₀ f₁ : PFunctor.B (P F) a → Cofix F
dxeq : dest x = abs { fst := a, snd := f₀ }
dyeq : dest y = abs { fst := a, snd := f₁ }
h' : ∀ (i : PFunctor.B (P F) a), r (f₀ i) (f₁ i)
⊢ abs { fst := a, snd := (Quot.mk fun x y => r x y) ∘ f₀ } = abs { fst := a, snd := (Quot.mk fun x y => r x y) ∘ f₁ }

Next tactic:
congr 2 with i
theorem Cofix.bisim (r : Cofix F → Cofix F → Prop)
    (h : ∀ x y, r x y → Liftr r (Cofix.dest x) (Cofix.dest y)) : ∀ x y, r x y → x = y := by
  apply Cofix.bisim_rel
  intro x y rxy
  rcases (liftr_iff r _ _).mp (h x y rxy) with ⟨a, f₀, f₁, dxeq, dyeq, h'⟩
  rw [dxeq, dyeq, ← abs_map, ← abs_map, PFunctor.map_eq, PFunctor.map_eq]
  congr 2 with i
  

Proof state:
case h.intro.intro.intro.intro.intro.e_a.e_snd.h
F : Type u → Type u
inst✝ : Functor F
q : QPF F
r : Cofix F → Cofix F → Prop
h : ∀ (x y : Cofix F), r x y → Liftr r (dest x) (dest y)
x y : Cofix F
rxy : r x y
a : (P F).A
f₀ f₁ : PFunctor.B (P F) a → Cofix F
dxeq : dest x = abs { fst := a, snd := f₀ }
dyeq : dest y = abs { fst := a, snd := f₁ }
h' : ∀ (i : PFunctor.B (P F) a), r (f₀ i) (f₁ i)
i : PFunctor.B (P F) a
⊢ ((Quot.mk fun x y => r x y) ∘ f₀) i = ((Quot.mk fun x y => r x y) ∘ f₁) i

Next tactic:
apply Quot.sound
theorem Cofix.bisim (r : Cofix F → Cofix F → Prop)
    (h : ∀ x y, r x y → Liftr r (Cofix.dest x) (Cofix.dest y)) : ∀ x y, r x y → x = y := by
  apply Cofix.bisim_rel
  intro x y rxy
  rcases (liftr_iff r _ _).mp (h x y rxy) with ⟨a, f₀, f₁, dxeq, dyeq, h'⟩
  rw [dxeq, dyeq, ← abs_map, ← abs_map, PFunctor.map_eq, PFunctor.map_eq]
  congr 2 with i
  apply Quot.sound
  

Proof state:
case h.intro.intro.intro.intro.intro.e_a.e_snd.h.a
F : Type u → Type u
inst✝ : Functor F
q : QPF F
r : Cofix F → Cofix F → Prop
h : ∀ (x y : Cofix F), r x y → Liftr r (dest x) (dest y)
x y : Cofix F
rxy : r x y
a : (P F).A
f₀ f₁ : PFunctor.B (P F) a → Cofix F
dxeq : dest x = abs { fst := a, snd := f₀ }
dyeq : dest y = abs { fst := a, snd := f₁ }
h' : ∀ (i : PFunctor.B (P F) a), r (f₀ i) (f₁ i)
i : PFunctor.B (P F) a
⊢ r (f₀ i) (f₁ i)

Next tactic:
apply h'
theorem Cofix.bisim' {α : Type*} (Q : α → Prop) (u v : α → Cofix F)
    (h : ∀ x, Q x → ∃ a f f', Cofix.dest (u x) = abs ⟨a, f⟩ ∧ Cofix.dest (v x) = abs ⟨a, f'⟩ ∧
      ∀ i, ∃ x', Q x' ∧ f i = u x' ∧ f' i = v x') :
    ∀ x, Q x → u x = v x := fun x Qx =>
  let R := fun w z : Cofix F => ∃ x', Q x' ∧ w = u x' ∧ z = v x'
  Cofix.bisim R
    (fun x y ⟨x', Qx', xeq, yeq⟩ => by
      

Proof state:
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u_1
Q : α → Prop
u v : α → Cofix F
h :
  ∀ (x : α),
    Q x →
      ∃ a f f',
        dest (u x) = abs { fst := a, snd := f } ∧
          dest (v x) = abs { fst := a, snd := f' } ∧ ∀ (i : PFunctor.B (P F) a), ∃ x', Q x' ∧ f i = u x' ∧ f' i = v x'
x✝¹ : α
Qx : Q x✝¹
R : Cofix F → Cofix F → Prop := fun w z => ∃ x', Q x' ∧ w = u x' ∧ z = v x'
x y : Cofix F
x✝ : R x y
x' : α
Qx' : Q x'
xeq : x = u x'
yeq : y = v x'
⊢ Liftr R (dest x) (dest y)

Next tactic:
rcases h x' Qx' with ⟨a, f, f', ux'eq, vx'eq, h'⟩
theorem Cofix.bisim' {α : Type*} (Q : α → Prop) (u v : α → Cofix F)
    (h : ∀ x, Q x → ∃ a f f', Cofix.dest (u x) = abs ⟨a, f⟩ ∧ Cofix.dest (v x) = abs ⟨a, f'⟩ ∧
      ∀ i, ∃ x', Q x' ∧ f i = u x' ∧ f' i = v x') :
    ∀ x, Q x → u x = v x := fun x Qx =>
  let R := fun w z : Cofix F => ∃ x', Q x' ∧ w = u x' ∧ z = v x'
  Cofix.bisim R
    (fun x y ⟨x', Qx', xeq, yeq⟩ => by
      rcases h x' Qx' with ⟨a, f, f', ux'eq, vx'eq, h'⟩
      

Proof state:
case intro.intro.intro.intro.intro
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u_1
Q : α → Prop
u v : α → Cofix F
h :
  ∀ (x : α),
    Q x →
      ∃ a f f',
        dest (u x) = abs { fst := a, snd := f } ∧
          dest (v x) = abs { fst := a, snd := f' } ∧ ∀ (i : PFunctor.B (P F) a), ∃ x', Q x' ∧ f i = u x' ∧ f' i = v x'
x✝¹ : α
Qx : Q x✝¹
R : Cofix F → Cofix F → Prop := fun w z => ∃ x', Q x' ∧ w = u x' ∧ z = v x'
x y : Cofix F
x✝ : R x y
x' : α
Qx' : Q x'
xeq : x = u x'
yeq : y = v x'
a : (P F).A
f f' : PFunctor.B (P F) a → Cofix F
ux'eq : dest (u x') = abs { fst := a, snd := f }
vx'eq : dest (v x') = abs { fst := a, snd := f' }
h' : ∀ (i : PFunctor.B (P F) a), ∃ x', Q x' ∧ f i = u x' ∧ f' i = v x'
⊢ Liftr R (dest x) (dest y)

Next tactic:
rw [liftr_iff]
theorem Cofix.bisim' {α : Type*} (Q : α → Prop) (u v : α → Cofix F)
    (h : ∀ x, Q x → ∃ a f f', Cofix.dest (u x) = abs ⟨a, f⟩ ∧ Cofix.dest (v x) = abs ⟨a, f'⟩ ∧
      ∀ i, ∃ x', Q x' ∧ f i = u x' ∧ f' i = v x') :
    ∀ x, Q x → u x = v x := fun x Qx =>
  let R := fun w z : Cofix F => ∃ x', Q x' ∧ w = u x' ∧ z = v x'
  Cofix.bisim R
    (fun x y ⟨x', Qx', xeq, yeq⟩ => by
      rcases h x' Qx' with ⟨a, f, f', ux'eq, vx'eq, h'⟩
      rw [liftr_iff]
      

Proof state:
case intro.intro.intro.intro.intro
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u_1
Q : α → Prop
u v : α → Cofix F
h :
  ∀ (x : α),
    Q x →
      ∃ a f f',
        dest (u x) = abs { fst := a, snd := f } ∧
          dest (v x) = abs { fst := a, snd := f' } ∧ ∀ (i : PFunctor.B (P F) a), ∃ x', Q x' ∧ f i = u x' ∧ f' i = v x'
x✝¹ : α
Qx : Q x✝¹
R : Cofix F → Cofix F → Prop := fun w z => ∃ x', Q x' ∧ w = u x' ∧ z = v x'
x y : Cofix F
x✝ : R x y
x' : α
Qx' : Q x'
xeq : x = u x'
yeq : y = v x'
a : (P F).A
f f' : PFunctor.B (P F) a → Cofix F
ux'eq : dest (u x') = abs { fst := a, snd := f }
vx'eq : dest (v x') = abs { fst := a, snd := f' }
h' : ∀ (i : PFunctor.B (P F) a), ∃ x', Q x' ∧ f i = u x' ∧ f' i = v x'
⊢ ∃ a f₀ f₁,
    dest x = abs { fst := a, snd := f₀ } ∧
      dest y = abs { fst := a, snd := f₁ } ∧ ∀ (i : PFunctor.B (P F) a), R (f₀ i) (f₁ i)

Next tactic:
refine' ⟨a, f, f', xeq.symm ▸ ux'eq, yeq.symm ▸ vx'eq, h'⟩
/-- composition of qpfs gives another qpf -/
def comp : QPF (Functor.Comp F₂ F₁) where
  P := PFunctor.comp q₂.P q₁.P
  abs {α} := by
    

Proof state:
F₂ : Type u → Type u
inst✝¹ : Functor F₂
q₂ : QPF F₂
F₁ : Type u → Type u
inst✝ : Functor F₁
q₁ : QPF F₁
α : Type u
⊢ ↑(PFunctor.comp (P F₂) (P F₁)) α → Functor.Comp F₂ F₁ α

Next tactic:
dsimp [Functor.Comp]
/-- composition of qpfs gives another qpf -/
def comp : QPF (Functor.Comp F₂ F₁) where
  P := PFunctor.comp q₂.P q₁.P
  abs {α} := by
    dsimp [Functor.Comp]
    

Proof state:
F₂ : Type u → Type u
inst✝¹ : Functor F₂
q₂ : QPF F₂
F₁ : Type u → Type u
inst✝ : Functor F₁
q₁ : QPF F₁
α : Type u
⊢ ↑(PFunctor.comp (P F₂) (P F₁)) α → F₂ (F₁ α)

Next tactic:
intro p
/-- composition of qpfs gives another qpf -/
def comp : QPF (Functor.Comp F₂ F₁) where
  P := PFunctor.comp q₂.P q₁.P
  abs {α} := by
    dsimp [Functor.Comp]
    intro p
    

Proof state:
F₂ : Type u → Type u
inst✝¹ : Functor F₂
q₂ : QPF F₂
F₁ : Type u → Type u
inst✝ : Functor F₁
q₁ : QPF F₁
α : Type u
p : ↑(PFunctor.comp (P F₂) (P F₁)) α
⊢ F₂ (F₁ α)

Next tactic:
exact abs ⟨p.1.1, fun x => abs ⟨p.1.2 x, fun y => p.2 ⟨x, y⟩⟩⟩
/-- composition of qpfs gives another qpf -/
def comp : QPF (Functor.Comp F₂ F₁) where
  P := PFunctor.comp q₂.P q₁.P
  abs {α} := by
    dsimp [Functor.Comp]
    intro p
    exact abs ⟨p.1.1, fun x => abs ⟨p.1.2 x, fun y => p.2 ⟨x, y⟩⟩⟩
  repr {α} := by
    

Proof state:
F₂ : Type u → Type u
inst✝¹ : Functor F₂
q₂ : QPF F₂
F₁ : Type u → Type u
inst✝ : Functor F₁
q₁ : QPF F₁
α : Type u
⊢ Functor.Comp F₂ F₁ α → ↑(PFunctor.comp (P F₂) (P F₁)) α

Next tactic:
dsimp [Functor.Comp]
/-- composition of qpfs gives another qpf -/
def comp : QPF (Functor.Comp F₂ F₁) where
  P := PFunctor.comp q₂.P q₁.P
  abs {α} := by
    dsimp [Functor.Comp]
    intro p
    exact abs ⟨p.1.1, fun x => abs ⟨p.1.2 x, fun y => p.2 ⟨x, y⟩⟩⟩
  repr {α} := by
    dsimp [Functor.Comp]
    

Proof state:
F₂ : Type u → Type u
inst✝¹ : Functor F₂
q₂ : QPF F₂
F₁ : Type u → Type u
inst✝ : Functor F₁
q₁ : QPF F₁
α : Type u
⊢ F₂ (F₁ α) → ↑(PFunctor.comp (P F₂) (P F₁)) α

Next tactic:
intro y
/-- composition of qpfs gives another qpf -/
def comp : QPF (Functor.Comp F₂ F₁) where
  P := PFunctor.comp q₂.P q₁.P
  abs {α} := by
    dsimp [Functor.Comp]
    intro p
    exact abs ⟨p.1.1, fun x => abs ⟨p.1.2 x, fun y => p.2 ⟨x, y⟩⟩⟩
  repr {α} := by
    dsimp [Functor.Comp]
    intro y
    

Proof state:
F₂ : Type u → Type u
inst✝¹ : Functor F₂
q₂ : QPF F₂
F₁ : Type u → Type u
inst✝ : Functor F₁
q₁ : QPF F₁
α : Type u
y : F₂ (F₁ α)
⊢ ↑(PFunctor.comp (P F₂) (P F₁)) α

Next tactic:
refine' ⟨⟨(repr y).1, fun u => (repr ((repr y).2 u)).1⟩, _⟩
/-- composition of qpfs gives another qpf -/
def comp : QPF (Functor.Comp F₂ F₁) where
  P := PFunctor.comp q₂.P q₁.P
  abs {α} := by
    dsimp [Functor.Comp]
    intro p
    exact abs ⟨p.1.1, fun x => abs ⟨p.1.2 x, fun y => p.2 ⟨x, y⟩⟩⟩
  repr {α} := by
    dsimp [Functor.Comp]
    intro y
    refine' ⟨⟨(repr y).1, fun u => (repr ((repr y).2 u)).1⟩, _⟩
    

Proof state:
F₂ : Type u → Type u
inst✝¹ : Functor F₂
q₂ : QPF F₂
F₁ : Type u → Type u
inst✝ : Functor F₁
q₁ : QPF F₁
α : Type u
y : F₂ (F₁ α)
⊢ PFunctor.B (PFunctor.comp (P F₂) (P F₁)) { fst := (repr y).fst, snd := fun u => (repr (Sigma.snd (repr y) u)).fst } →
    α

Next tactic:
dsimp [PFunctor.comp]
/-- composition of qpfs gives another qpf -/
def comp : QPF (Functor.Comp F₂ F₁) where
  P := PFunctor.comp q₂.P q₁.P
  abs {α} := by
    dsimp [Functor.Comp]
    intro p
    exact abs ⟨p.1.1, fun x => abs ⟨p.1.2 x, fun y => p.2 ⟨x, y⟩⟩⟩
  repr {α} := by
    dsimp [Functor.Comp]
    intro y
    refine' ⟨⟨(repr y).1, fun u => (repr ((repr y).2 u)).1⟩, _⟩
    dsimp [PFunctor.comp]
    

Proof state:
F₂ : Type u → Type u
inst✝¹ : Functor F₂
q₂ : QPF F₂
F₁ : Type u → Type u
inst✝ : Functor F₁
q₁ : QPF F₁
α : Type u
y : F₂ (F₁ α)
⊢ (u : PFunctor.B (P F₂) (repr y).fst) × PFunctor.B (P F₁) (repr (Sigma.snd (repr y) u)).fst → α

Next tactic:
intro x
/-- composition of qpfs gives another qpf -/
def comp : QPF (Functor.Comp F₂ F₁) where
  P := PFunctor.comp q₂.P q₁.P
  abs {α} := by
    dsimp [Functor.Comp]
    intro p
    exact abs ⟨p.1.1, fun x => abs ⟨p.1.2 x, fun y => p.2 ⟨x, y⟩⟩⟩
  repr {α} := by
    dsimp [Functor.Comp]
    intro y
    refine' ⟨⟨(repr y).1, fun u => (repr ((repr y).2 u)).1⟩, _⟩
    dsimp [PFunctor.comp]
    intro x
    

Proof state:
F₂ : Type u → Type u
inst✝¹ : Functor F₂
q₂ : QPF F₂
F₁ : Type u → Type u
inst✝ : Functor F₁
q₁ : QPF F₁
α : Type u
y : F₂ (F₁ α)
x : (u : PFunctor.B (P F₂) (repr y).fst) × PFunctor.B (P F₁) (repr (Sigma.snd (repr y) u)).fst
⊢ α

Next tactic:
exact (repr ((repr y).2 x.1)).snd x.2
/-- composition of qpfs gives another qpf -/
def comp : QPF (Functor.Comp F₂ F₁) where
  P := PFunctor.comp q₂.P q₁.P
  abs {α} := by
    dsimp [Functor.Comp]
    intro p
    exact abs ⟨p.1.1, fun x => abs ⟨p.1.2 x, fun y => p.2 ⟨x, y⟩⟩⟩
  repr {α} := by
    dsimp [Functor.Comp]
    intro y
    refine' ⟨⟨(repr y).1, fun u => (repr ((repr y).2 u)).1⟩, _⟩
    dsimp [PFunctor.comp]
    intro x
    exact (repr ((repr y).2 x.1)).snd x.2
  abs_repr {α} := by
    

Proof state:
F₂ : Type u → Type u
inst✝¹ : Functor F₂
q₂ : QPF F₂
F₁ : Type u → Type u
inst✝ : Functor F₁
q₁ : QPF F₁
α : Type u
⊢ ∀ (x : Functor.Comp F₂ F₁ α),
    (fun {α} =>
          id fun p =>
            abs
              { fst := p.fst.fst,
                snd := fun x => abs { fst := Sigma.snd p.fst x, snd := fun y => Sigma.snd p { fst := x, snd := y } } })
        ((fun {α} =>
            id fun y =>
              { fst := { fst := (repr y).fst, snd := fun u => (repr (Sigma.snd (repr y) u)).fst },
                snd := id fun x => Sigma.snd (repr (Sigma.snd (repr y) x.fst)) x.snd })
          x) =
      x

Next tactic:
dsimp [Functor.Comp]
/-- composition of qpfs gives another qpf -/
def comp : QPF (Functor.Comp F₂ F₁) where
  P := PFunctor.comp q₂.P q₁.P
  abs {α} := by
    dsimp [Functor.Comp]
    intro p
    exact abs ⟨p.1.1, fun x => abs ⟨p.1.2 x, fun y => p.2 ⟨x, y⟩⟩⟩
  repr {α} := by
    dsimp [Functor.Comp]
    intro y
    refine' ⟨⟨(repr y).1, fun u => (repr ((repr y).2 u)).1⟩, _⟩
    dsimp [PFunctor.comp]
    intro x
    exact (repr ((repr y).2 x.1)).snd x.2
  abs_repr {α} := by
    dsimp [Functor.Comp]
    

Proof state:
F₂ : Type u → Type u
inst✝¹ : Functor F₂
q₂ : QPF F₂
F₁ : Type u → Type u
inst✝ : Functor F₁
q₁ : QPF F₁
α : Type u
⊢ ∀ (x : F₂ (F₁ α)),
    abs
        { fst := (repr x).fst,
          snd := fun x_1 =>
            abs
              { fst := (repr (Sigma.snd (repr x) x_1)).fst,
                snd := fun y => Sigma.snd (repr (Sigma.snd (repr x) x_1)) y } } =
      x

Next tactic:
intro x
/-- composition of qpfs gives another qpf -/
def comp : QPF (Functor.Comp F₂ F₁) where
  P := PFunctor.comp q₂.P q₁.P
  abs {α} := by
    dsimp [Functor.Comp]
    intro p
    exact abs ⟨p.1.1, fun x => abs ⟨p.1.2 x, fun y => p.2 ⟨x, y⟩⟩⟩
  repr {α} := by
    dsimp [Functor.Comp]
    intro y
    refine' ⟨⟨(repr y).1, fun u => (repr ((repr y).2 u)).1⟩, _⟩
    dsimp [PFunctor.comp]
    intro x
    exact (repr ((repr y).2 x.1)).snd x.2
  abs_repr {α} := by
    dsimp [Functor.Comp]
    intro x
    

Proof state:
F₂ : Type u → Type u
inst✝¹ : Functor F₂
q₂ : QPF F₂
F₁ : Type u → Type u
inst✝ : Functor F₁
q₁ : QPF F₁
α : Type u
x : F₂ (F₁ α)
⊢ abs
      { fst := (repr x).fst,
        snd := fun x_1 =>
          abs
            { fst := (repr (Sigma.snd (repr x) x_1)).fst,
              snd := fun y => Sigma.snd (repr (Sigma.snd (repr x) x_1)) y } } =
    x

Next tactic:
conv =>
      rhs
      rw [← abs_repr x]
/-- composition of qpfs gives another qpf -/
def comp : QPF (Functor.Comp F₂ F₁) where
  P := PFunctor.comp q₂.P q₁.P
  abs {α} := by
    dsimp [Functor.Comp]
    intro p
    exact abs ⟨p.1.1, fun x => abs ⟨p.1.2 x, fun y => p.2 ⟨x, y⟩⟩⟩
  repr {α} := by
    dsimp [Functor.Comp]
    intro y
    refine' ⟨⟨(repr y).1, fun u => (repr ((repr y).2 u)).1⟩, _⟩
    dsimp [PFunctor.comp]
    intro x
    exact (repr ((repr y).2 x.1)).snd x.2
  abs_repr {α} := by
    dsimp [Functor.Comp]
    intro x
    conv =>
      

Proof state:
F₂ : Type u → Type u
inst✝¹ : Functor F₂
q₂ : QPF F₂
F₁ : Type u → Type u
inst✝ : Functor F₁
q₁ : QPF F₁
α : Type u
x : F₂ (F₁ α)
| abs
      { fst := (repr x).fst,
        snd := fun x_1 =>
          abs
            { fst := (repr (Sigma.snd (repr x) x_1)).fst,
              snd := fun y => Sigma.snd (repr (Sigma.snd (repr x) x_1)) y } } =
    x

Next tactic:
rhs
      rw [← abs_repr x]
/-- composition of qpfs gives another qpf -/
def comp : QPF (Functor.Comp F₂ F₁) where
  P := PFunctor.comp q₂.P q₁.P
  abs {α} := by
    dsimp [Functor.Comp]
    intro p
    exact abs ⟨p.1.1, fun x => abs ⟨p.1.2 x, fun y => p.2 ⟨x, y⟩⟩⟩
  repr {α} := by
    dsimp [Functor.Comp]
    intro y
    refine' ⟨⟨(repr y).1, fun u => (repr ((repr y).2 u)).1⟩, _⟩
    dsimp [PFunctor.comp]
    intro x
    exact (repr ((repr y).2 x.1)).snd x.2
  abs_repr {α} := by
    dsimp [Functor.Comp]
    intro x
    conv =>
      

Proof state:
F₂ : Type u → Type u
inst✝¹ : Functor F₂
q₂ : QPF F₂
F₁ : Type u → Type u
inst✝ : Functor F₁
q₁ : QPF F₁
α : Type u
x : F₂ (F₁ α)
| abs
      { fst := (repr x).fst,
        snd := fun x_1 =>
          abs
            { fst := (repr (Sigma.snd (repr x) x_1)).fst,
              snd := fun y => Sigma.snd (repr (Sigma.snd (repr x) x_1)) y } } =
    x

Next tactic:
rhs
/-- composition of qpfs gives another qpf -/
def comp : QPF (Functor.Comp F₂ F₁) where
  P := PFunctor.comp q₂.P q₁.P
  abs {α} := by
    dsimp [Functor.Comp]
    intro p
    exact abs ⟨p.1.1, fun x => abs ⟨p.1.2 x, fun y => p.2 ⟨x, y⟩⟩⟩
  repr {α} := by
    dsimp [Functor.Comp]
    intro y
    refine' ⟨⟨(repr y).1, fun u => (repr ((repr y).2 u)).1⟩, _⟩
    dsimp [PFunctor.comp]
    intro x
    exact (repr ((repr y).2 x.1)).snd x.2
  abs_repr {α} := by
    dsimp [Functor.Comp]
    intro x
    conv =>
      rhs
      

Proof state:
F₂ : Type u → Type u
inst✝¹ : Functor F₂
q₂ : QPF F₂
F₁ : Type u → Type u
inst✝ : Functor F₁
q₁ : QPF F₁
α : Type u
x : F₂ (F₁ α)
| x

Next tactic:
rw [← abs_repr x]
/-- composition of qpfs gives another qpf -/
def comp : QPF (Functor.Comp F₂ F₁) where
  P := PFunctor.comp q₂.P q₁.P
  abs {α} := by
    dsimp [Functor.Comp]
    intro p
    exact abs ⟨p.1.1, fun x => abs ⟨p.1.2 x, fun y => p.2 ⟨x, y⟩⟩⟩
  repr {α} := by
    dsimp [Functor.Comp]
    intro y
    refine' ⟨⟨(repr y).1, fun u => (repr ((repr y).2 u)).1⟩, _⟩
    dsimp [PFunctor.comp]
    intro x
    exact (repr ((repr y).2 x.1)).snd x.2
  abs_repr {α} := by
    dsimp [Functor.Comp]
    intro x
    conv =>
      rhs
      rw [← abs_repr x]
    

Proof state:
F₂ : Type u → Type u
inst✝¹ : Functor F₂
q₂ : QPF F₂
F₁ : Type u → Type u
inst✝ : Functor F₁
q₁ : QPF F₁
α : Type u
x : F₂ (F₁ α)
⊢ abs
      { fst := (repr x).fst,
        snd := fun x_1 =>
          abs
            { fst := (repr (Sigma.snd (repr x) x_1)).fst,
              snd := fun y => Sigma.snd (repr (Sigma.snd (repr x) x_1)) y } } =
    abs (repr x)

Next tactic:
cases' h : repr x with a f