l3lab/ntp-mathlib huggingface dataset:
/-- 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]
    cases' h : repr x with a f
    dsimp
    congr with x
    cases' h' : repr (f x) with b g
    dsimp; rw [← h', abs_repr]
  abs_map {α β} f := by
    dsimp (config := { unfoldPartialApp := true }) [Functor.Comp, PFunctor.comp]
    intro p
    cases' p with a g; dsimp
    cases' a with b h; dsimp
    symm
    trans
    symm
    

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 : α → β
b : (P F₂).A
h : PFunctor.B (P F₂) b → (P F₁).A
g :
  PFunctor.B
      { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
        B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
      { fst := b, snd := h } →
    α
⊢ ?a = f <$> abs { fst := b, snd := fun x => abs { fst := h x, snd := fun y => g { fst := x, snd := y } } }
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 : α → β
b : (P F₂).A
h : PFunctor.B (P F₂) b → (P F₁).A
g :
  PFunctor.B
      { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
        B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
      { fst := b, snd := h } →
    α
⊢ ?a =
    abs
      {
        fst :=
          (PFunctor.map
                { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
                  B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
                f { fst := { fst := b, snd := h }, snd := g }).fst.fst,
        snd := fun x =>
          abs
            {
              fst :=
                Sigma.snd
                  (PFunctor.map
                      { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
                        B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
                      f { fst := { fst := b, snd := h }, snd := g }).fst
                  x,
              snd := fun y =>
                Sigma.snd
                  (PFunctor.map
                    { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
                      B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
                    f { fst := { fst := b, snd := h }, snd := g })
                  { fst := x, snd := y } } }

Next tactic:
apply abs_map
/-- 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]
    cases' h : repr x with a f
    dsimp
    congr with x
    cases' h' : repr (f x) with b g
    dsimp; rw [← h', abs_repr]
  abs_map {α β} f := by
    dsimp (config := { unfoldPartialApp := true }) [Functor.Comp, PFunctor.comp]
    intro p
    cases' p with a g; dsimp
    cases' a with b h; dsimp
    symm
    trans
    symm
    apply abs_map
    

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 : α → β
b : (P F₂).A
h : PFunctor.B (P F₂) b → (P F₁).A
g :
  PFunctor.B
      { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
        B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
      { fst := b, snd := h } →
    α
⊢ abs
      (PFunctor.map (P F₂) (fun x => f <$> x)
        { fst := b, snd := fun x => abs { fst := h x, snd := fun y => g { fst := x, snd := y } } }) =
    abs
      {
        fst :=
          (PFunctor.map
                { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
                  B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
                f { fst := { fst := b, snd := h }, snd := g }).fst.fst,
        snd := fun x =>
          abs
            {
              fst :=
                Sigma.snd
                  (PFunctor.map
                      { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
                        B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
                      f { fst := { fst := b, snd := h }, snd := g }).fst
                  x,
              snd := fun y =>
                Sigma.snd
                  (PFunctor.map
                    { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
                      B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
                    f { fst := { fst := b, snd := h }, snd := g })
                  { fst := x, snd := y } } }

Next tactic:
congr
/-- 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]
    cases' h : repr x with a f
    dsimp
    congr with x
    cases' h' : repr (f x) with b g
    dsimp; rw [← h', abs_repr]
  abs_map {α β} f := by
    dsimp (config := { unfoldPartialApp := true }) [Functor.Comp, PFunctor.comp]
    intro p
    cases' p with a g; dsimp
    cases' a with b h; dsimp
    symm
    trans
    symm
    apply abs_map
    congr
    

Proof state:
case e_a
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 : α → β
b : (P F₂).A
h : PFunctor.B (P F₂) b → (P F₁).A
g :
  PFunctor.B
      { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
        B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
      { fst := b, snd := h } →
    α
⊢ PFunctor.map (P F₂) (fun x => f <$> x)
      { fst := b, snd := fun x => abs { fst := h x, snd := fun y => g { fst := x, snd := y } } } =
    {
      fst :=
        (PFunctor.map
              { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
                B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
              f { fst := { fst := b, snd := h }, snd := g }).fst.fst,
      snd := fun x =>
        abs
          {
            fst :=
              Sigma.snd
                (PFunctor.map
                    { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
                      B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
                    f { fst := { fst := b, snd := h }, snd := g }).fst
                x,
            snd := fun y =>
              Sigma.snd
                (PFunctor.map
                  { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
                    B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
                  f { fst := { fst := b, snd := h }, snd := g })
                { fst := x, snd := y } } }

Next tactic:
rw [PFunctor.map_eq]
/-- 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]
    cases' h : repr x with a f
    dsimp
    congr with x
    cases' h' : repr (f x) with b g
    dsimp; rw [← h', abs_repr]
  abs_map {α β} f := by
    dsimp (config := { unfoldPartialApp := true }) [Functor.Comp, PFunctor.comp]
    intro p
    cases' p with a g; dsimp
    cases' a with b h; dsimp
    symm
    trans
    symm
    apply abs_map
    congr
    rw [PFunctor.map_eq]
    

Proof state:
case e_a
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 : α → β
b : (P F₂).A
h : PFunctor.B (P F₂) b → (P F₁).A
g :
  PFunctor.B
      { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
        B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
      { fst := b, snd := h } →
    α
⊢ { fst := b, snd := (fun x => f <$> x) ∘ fun x => abs { fst := h x, snd := fun y => g { fst := x, snd := y } } } =
    {
      fst :=
        (PFunctor.map
              { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
                B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
              f { fst := { fst := b, snd := h }, snd := g }).fst.fst,
      snd := fun x =>
        abs
          {
            fst :=
              Sigma.snd
                (PFunctor.map
                    { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
                      B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
                    f { fst := { fst := b, snd := h }, snd := g }).fst
                x,
            snd := fun y =>
              Sigma.snd
                (PFunctor.map
                  { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
                    B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
                  f { fst := { fst := b, snd := h }, snd := g })
                { fst := x, snd := y } } }

Next tactic:
dsimp [Function.comp_def]
/-- 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]
    cases' h : repr x with a f
    dsimp
    congr with x
    cases' h' : repr (f x) with b g
    dsimp; rw [← h', abs_repr]
  abs_map {α β} f := by
    dsimp (config := { unfoldPartialApp := true }) [Functor.Comp, PFunctor.comp]
    intro p
    cases' p with a g; dsimp
    cases' a with b h; dsimp
    symm
    trans
    symm
    apply abs_map
    congr
    rw [PFunctor.map_eq]
    dsimp [Function.comp_def]
    

Proof state:
case e_a
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 : α → β
b : (P F₂).A
h : PFunctor.B (P F₂) b → (P F₁).A
g :
  PFunctor.B
      { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
        B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
      { fst := b, snd := h } →
    α
⊢ { fst := b, snd := fun x => f <$> abs { fst := h x, snd := fun y => g { fst := x, snd := y } } } =
    {
      fst :=
        (PFunctor.map
              { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
                B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
              f { fst := { fst := b, snd := h }, snd := g }).fst.fst,
      snd := fun x =>
        abs
          {
            fst :=
              Sigma.snd
                (PFunctor.map
                    { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
                      B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
                    f { fst := { fst := b, snd := h }, snd := g }).fst
                x,
            snd := fun y =>
              Sigma.snd
                (PFunctor.map
                  { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
                    B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
                  f { fst := { fst := b, snd := h }, snd := g })
                { fst := x, snd := y } } }

Next tactic:
congr
/-- 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]
    cases' h : repr x with a f
    dsimp
    congr with x
    cases' h' : repr (f x) with b g
    dsimp; rw [← h', abs_repr]
  abs_map {α β} f := by
    dsimp (config := { unfoldPartialApp := true }) [Functor.Comp, PFunctor.comp]
    intro p
    cases' p with a g; dsimp
    cases' a with b h; dsimp
    symm
    trans
    symm
    apply abs_map
    congr
    rw [PFunctor.map_eq]
    dsimp [Function.comp_def]
    congr
    

Proof state:
case e_a.e_snd
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 : α → β
b : (P F₂).A
h : PFunctor.B (P F₂) b → (P F₁).A
g :
  PFunctor.B
      { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
        B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
      { fst := b, snd := h } →
    α
⊢ (fun x => f <$> abs { fst := h x, snd := fun y => g { fst := x, snd := y } }) = fun x =>
    abs
      {
        fst :=
          Sigma.snd
            (PFunctor.map
                { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
                  B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
                f { fst := { fst := b, snd := h }, snd := g }).fst
            x,
        snd := fun y =>
          Sigma.snd
            (PFunctor.map
              { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
                B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
              f { fst := { fst := b, snd := h }, snd := g })
            { fst := x, snd := y } }

Next tactic:
ext 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]
    cases' h : repr x with a f
    dsimp
    congr with x
    cases' h' : repr (f x) with b g
    dsimp; rw [← h', abs_repr]
  abs_map {α β} f := by
    dsimp (config := { unfoldPartialApp := true }) [Functor.Comp, PFunctor.comp]
    intro p
    cases' p with a g; dsimp
    cases' a with b h; dsimp
    symm
    trans
    symm
    apply abs_map
    congr
    rw [PFunctor.map_eq]
    dsimp [Function.comp_def]
    congr
    ext x
    

Proof state:
case e_a.e_snd.h
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 : α → β
b : (P F₂).A
h : PFunctor.B (P F₂) b → (P F₁).A
g :
  PFunctor.B
      { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
        B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
      { fst := b, snd := h } →
    α
x : PFunctor.B (P F₂) b
⊢ f <$> abs { fst := h x, snd := fun y => g { fst := x, snd := y } } =
    abs
      {
        fst :=
          Sigma.snd
            (PFunctor.map
                { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
                  B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
                f { fst := { fst := b, snd := h }, snd := g }).fst
            x,
        snd := fun y =>
          Sigma.snd
            (PFunctor.map
              { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
                B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
              f { fst := { fst := b, snd := h }, snd := g })
            { fst := x, snd := y } }

Next tactic:
rw [← abs_map]
/-- 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]
    cases' h : repr x with a f
    dsimp
    congr with x
    cases' h' : repr (f x) with b g
    dsimp; rw [← h', abs_repr]
  abs_map {α β} f := by
    dsimp (config := { unfoldPartialApp := true }) [Functor.Comp, PFunctor.comp]
    intro p
    cases' p with a g; dsimp
    cases' a with b h; dsimp
    symm
    trans
    symm
    apply abs_map
    congr
    rw [PFunctor.map_eq]
    dsimp [Function.comp_def]
    congr
    ext x
    rw [← abs_map]
    

Proof state:
case e_a.e_snd.h
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 : α → β
b : (P F₂).A
h : PFunctor.B (P F₂) b → (P F₁).A
g :
  PFunctor.B
      { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
        B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
      { fst := b, snd := h } →
    α
x : PFunctor.B (P F₂) b
⊢ abs (PFunctor.map (P F₁) f { fst := h x, snd := fun y => g { fst := x, snd := y } }) =
    abs
      {
        fst :=
          Sigma.snd
            (PFunctor.map
                { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
                  B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
                f { fst := { fst := b, snd := h }, snd := g }).fst
            x,
        snd := fun y =>
          Sigma.snd
            (PFunctor.map
              { A := (a₂ : (P F₂).A) × (PFunctor.B (P F₂) a₂ → (P F₁).A),
                B := fun a₂a₁ => (u : PFunctor.B (P F₂) a₂a₁.fst) × PFunctor.B (P F₁) (Sigma.snd a₂a₁ u) }
              f { fst := { fst := b, snd := h }, snd := g })
            { fst := x, snd := y } }

Next tactic:
rfl
/-- Given a qpf `F` and a well-behaved surjection `FG_abs` from `F α` to
functor `G α`, `G` is a qpf. We can consider `G` a quotient on `F` where
elements `x y : F α` are in the same equivalence class if
`FG_abs x = FG_abs y`. -/
def quotientQPF (FG_abs_repr : ∀ {α} (x : G α), FG_abs (FG_repr x) = x)
    (FG_abs_map : ∀ {α β} (f : α → β) (x : F α), FG_abs (f <$> x) = f <$> FG_abs x) : QPF G where
  P := q.P
  abs {α} p := FG_abs (abs p)
  repr {α} x := repr (FG_repr x)
  abs_repr {α} x := by 

Proof state:
F : Type u → Type u
inst✝¹ : Functor F
q : QPF F
G : Type u → Type u
inst✝ : Functor G
FG_abs : {α : Type u} → F α → G α
FG_repr : {α : Type u} → G α → F α
FG_abs_repr : ∀ {α : Type u} (x : G α), FG_abs (FG_repr x) = x
FG_abs_map : ∀ {α β : Type u} (f : α → β) (x : F α), FG_abs (f <$> x) = f <$> FG_abs x
α : Type u
x : G α
⊢ (fun {α} p => FG_abs (abs p)) ((fun {α} x => repr (FG_repr x)) x) = x

Next tactic:
simp only
/-- Given a qpf `F` and a well-behaved surjection `FG_abs` from `F α` to
functor `G α`, `G` is a qpf. We can consider `G` a quotient on `F` where
elements `x y : F α` are in the same equivalence class if
`FG_abs x = FG_abs y`. -/
def quotientQPF (FG_abs_repr : ∀ {α} (x : G α), FG_abs (FG_repr x) = x)
    (FG_abs_map : ∀ {α β} (f : α → β) (x : F α), FG_abs (f <$> x) = f <$> FG_abs x) : QPF G where
  P := q.P
  abs {α} p := FG_abs (abs p)
  repr {α} x := repr (FG_repr x)
  abs_repr {α} x := by simp only; 

Proof state:
F : Type u → Type u
inst✝¹ : Functor F
q : QPF F
G : Type u → Type u
inst✝ : Functor G
FG_abs : {α : Type u} → F α → G α
FG_repr : {α : Type u} → G α → F α
FG_abs_repr : ∀ {α : Type u} (x : G α), FG_abs (FG_repr x) = x
FG_abs_map : ∀ {α β : Type u} (f : α → β) (x : F α), FG_abs (f <$> x) = f <$> FG_abs x
α : Type u
x : G α
⊢ FG_abs (abs (repr (FG_repr x))) = x

Next tactic:
rw [abs_repr, FG_abs_repr]
/-- Given a qpf `F` and a well-behaved surjection `FG_abs` from `F α` to
functor `G α`, `G` is a qpf. We can consider `G` a quotient on `F` where
elements `x y : F α` are in the same equivalence class if
`FG_abs x = FG_abs y`. -/
def quotientQPF (FG_abs_repr : ∀ {α} (x : G α), FG_abs (FG_repr x) = x)
    (FG_abs_map : ∀ {α β} (f : α → β) (x : F α), FG_abs (f <$> x) = f <$> FG_abs x) : QPF G where
  P := q.P
  abs {α} p := FG_abs (abs p)
  repr {α} x := repr (FG_repr x)
  abs_repr {α} x := by simp only; rw [abs_repr, FG_abs_repr]
  abs_map {α β} f x := by 

Proof state:
F : Type u → Type u
inst✝¹ : Functor F
q : QPF F
G : Type u → Type u
inst✝ : Functor G
FG_abs : {α : Type u} → F α → G α
FG_repr : {α : Type u} → G α → F α
FG_abs_repr : ∀ {α : Type u} (x : G α), FG_abs (FG_repr x) = x
FG_abs_map : ∀ {α β : Type u} (f : α → β) (x : F α), FG_abs (f <$> x) = f <$> FG_abs x
α β : Type u
f : α → β
x : ↑(P F) α
⊢ (fun {α} p => FG_abs (abs p)) (PFunctor.map (P F) f x) = f <$> (fun {α} p => FG_abs (abs p)) x

Next tactic:
simp only
/-- Given a qpf `F` and a well-behaved surjection `FG_abs` from `F α` to
functor `G α`, `G` is a qpf. We can consider `G` a quotient on `F` where
elements `x y : F α` are in the same equivalence class if
`FG_abs x = FG_abs y`. -/
def quotientQPF (FG_abs_repr : ∀ {α} (x : G α), FG_abs (FG_repr x) = x)
    (FG_abs_map : ∀ {α β} (f : α → β) (x : F α), FG_abs (f <$> x) = f <$> FG_abs x) : QPF G where
  P := q.P
  abs {α} p := FG_abs (abs p)
  repr {α} x := repr (FG_repr x)
  abs_repr {α} x := by simp only; rw [abs_repr, FG_abs_repr]
  abs_map {α β} f x := by simp only; 

Proof state:
F : Type u → Type u
inst✝¹ : Functor F
q : QPF F
G : Type u → Type u
inst✝ : Functor G
FG_abs : {α : Type u} → F α → G α
FG_repr : {α : Type u} → G α → F α
FG_abs_repr : ∀ {α : Type u} (x : G α), FG_abs (FG_repr x) = x
FG_abs_map : ∀ {α β : Type u} (f : α → β) (x : F α), FG_abs (f <$> x) = f <$> FG_abs x
α β : Type u
f : α → β
x : ↑(P F) α
⊢ FG_abs (abs (PFunctor.map (P F) f x)) = f <$> FG_abs (abs x)

Next tactic:
rw [abs_map, FG_abs_map]
theorem mem_supp {α : Type u} (x : F α) (u : α) :
    u ∈ supp x ↔ ∀ a f, abs ⟨a, f⟩ = x → u ∈ f '' univ := by
  

Proof state:
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
x : F α
u : α
⊢ u ∈ supp x ↔ ∀ (a : (P F).A) (f : PFunctor.B (P F) a → α), abs { fst := a, snd := f } = x → u ∈ f '' univ

Next tactic:
rw [supp]