l3lab/ntp-mathlib huggingface dataset:
/-- For `n ≠ 1`, `(n-1)!` is congruent to `-1` modulo `n` only if n is prime. -/
theorem prime_of_fac_equiv_neg_one (h : ((n - 1)! : ZMod n) = -1) (h1 : n ≠ 1) : Prime n := by
  rcases eq_or_ne n 0 with (rfl | h0)
  · norm_num at h
  replace h1 : 1 < n := n.two_le_iff.mpr ⟨h0, h1⟩
  by_contra h2
  obtain ⟨m, hm1, hm2 : 1 < m, hm3⟩ := exists_dvd_of_not_prime2 h1 h2
  have hm : m ∣ (n - 1)! := Nat.dvd_factorial (pos_of_gt hm2) (le_pred_of_lt hm3)
  refine' hm2.ne' (Nat.dvd_one.mp ((Nat.dvd_add_right hm).mp (hm1.trans _)))
  

Proof state:
case inr.intro.intro.intro
n : ℕ
h : ↑(n - 1)! = -1
h0 : n ≠ 0
h1 : 1 < n
h2 : ¬Prime n
m : ℕ
hm1 : m ∣ n
hm2 : 1 < m
hm3 : m < n
hm : m ∣ (n - 1)!
⊢ n ∣ (n - 1)! + 1

Next tactic:
rw [← ZMod.nat_cast_zmod_eq_zero_iff_dvd, cast_add, cast_one, h, add_left_neg]
/-- **Wilson's Theorem**: For `n ≠ 1`, `(n-1)!` is congruent to `-1` modulo `n` iff n is prime. -/
theorem prime_iff_fac_equiv_neg_one (h : n ≠ 1) : Prime n ↔ ((n - 1)! : ZMod n) = -1 := by
  

Proof state:
n : ℕ
h : n ≠ 1
⊢ Prime n ↔ ↑(n - 1)! = -1

Next tactic:
refine' ⟨fun h1 => _, fun h2 => prime_of_fac_equiv_neg_one h2 h⟩
/-- **Wilson's Theorem**: For `n ≠ 1`, `(n-1)!` is congruent to `-1` modulo `n` iff n is prime. -/
theorem prime_iff_fac_equiv_neg_one (h : n ≠ 1) : Prime n ↔ ((n - 1)! : ZMod n) = -1 := by
  refine' ⟨fun h1 => _, fun h2 => prime_of_fac_equiv_neg_one h2 h⟩
  

Proof state:
n : ℕ
h : n ≠ 1
h1 : Prime n
⊢ ↑(n - 1)! = -1

Next tactic:
haveI := Fact.mk h1
/-- **Wilson's Theorem**: For `n ≠ 1`, `(n-1)!` is congruent to `-1` modulo `n` iff n is prime. -/
theorem prime_iff_fac_equiv_neg_one (h : n ≠ 1) : Prime n ↔ ((n - 1)! : ZMod n) = -1 := by
  refine' ⟨fun h1 => _, fun h2 => prime_of_fac_equiv_neg_one h2 h⟩
  haveI := Fact.mk h1
  

Proof state:
n : ℕ
h : n ≠ 1
h1 : Prime n
this : Fact (Prime n)
⊢ ↑(n - 1)! = -1

Next tactic:
exact ZMod.wilsons_lemma n
theorem id_map {α : Type _} (x : F α) : id <$> x = x := by
  

Proof state:
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
x : F α
⊢ id <$> x = x

Next tactic:
rw [← abs_repr x]
theorem id_map {α : Type _} (x : F α) : id <$> x = x := by
  rw [← abs_repr x]
  

Proof state:
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
x : F α
⊢ id <$> abs (repr x) = abs (repr x)

Next tactic:
cases' repr x with a f
theorem id_map {α : Type _} (x : F α) : id <$> x = x := by
  rw [← abs_repr x]
  cases' repr x with a f
  

Proof state:
case mk
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
x : F α
a : (P F).A
f : PFunctor.B (P F) a → α
⊢ id <$> abs { fst := a, snd := f } = abs { fst := a, snd := f }

Next tactic:
rw [← abs_map]
theorem id_map {α : Type _} (x : F α) : id <$> x = x := by
  rw [← abs_repr x]
  cases' repr x with a f
  rw [← abs_map]
  

Proof state:
case mk
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
x : F α
a : (P F).A
f : PFunctor.B (P F) a → α
⊢ abs (PFunctor.map (P F) id { fst := a, snd := f }) = abs { fst := a, snd := f }

Next tactic:
rfl
theorem comp_map {α β γ : Type _} (f : α → β) (g : β → γ) (x : F α) :
    (g ∘ f) <$> x = g <$> f <$> x := by
  

Proof state:
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α β γ : Type u
f : α → β
g : β → γ
x : F α
⊢ (g ∘ f) <$> x = g <$> f <$> x

Next tactic:
rw [← abs_repr x]
theorem comp_map {α β γ : Type _} (f : α → β) (g : β → γ) (x : F α) :
    (g ∘ f) <$> x = g <$> f <$> x := by
  rw [← abs_repr x]
  

Proof state:
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α β γ : Type u
f : α → β
g : β → γ
x : F α
⊢ (g ∘ f) <$> abs (repr x) = g <$> f <$> abs (repr x)

Next tactic:
cases' repr x with a f
theorem comp_map {α β γ : Type _} (f : α → β) (g : β → γ) (x : F α) :
    (g ∘ f) <$> x = g <$> f <$> x := by
  rw [← abs_repr x]
  cases' repr x with a f
  

Proof state:
case mk
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α β γ : Type u
f✝ : α → β
g : β → γ
x : F α
a : (P F).A
f : PFunctor.B (P F) a → α
⊢ (g ∘ f✝) <$> abs { fst := a, snd := f } = g <$> f✝ <$> abs { fst := a, snd := f }

Next tactic:
rw [← abs_map, ← abs_map, ← abs_map]
theorem comp_map {α β γ : Type _} (f : α → β) (g : β → γ) (x : F α) :
    (g ∘ f) <$> x = g <$> f <$> x := by
  rw [← abs_repr x]
  cases' repr x with a f
  rw [← abs_map, ← abs_map, ← abs_map]
  

Proof state:
case mk
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α β γ : Type u
f✝ : α → β
g : β → γ
x : F α
a : (P F).A
f : PFunctor.B (P F) a → α
⊢ abs (PFunctor.map (P F) (g ∘ f✝) { fst := a, snd := f }) =
    abs (PFunctor.map (P F) g (PFunctor.map (P F) f✝ { fst := a, snd := f }))

Next tactic:
rfl
theorem liftp_iff {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ a f, x = abs ⟨a, f⟩ ∧ ∀ i, p (f i) := by
  

Proof state:
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
⊢ Liftp p x ↔ ∃ a f, x = abs { fst := a, snd := f } ∧ ∀ (i : PFunctor.B (P F) a), p (f i)

Next tactic:
constructor
theorem liftp_iff {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ a f, x = abs ⟨a, f⟩ ∧ ∀ i, p (f i) := by
  constructor
  · 

Proof state:
case mp
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
⊢ Liftp p x → ∃ a f, x = abs { fst := a, snd := f } ∧ ∀ (i : PFunctor.B (P F) a), p (f i)

Next tactic:
rintro ⟨y, hy⟩
theorem liftp_iff {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ a f, x = abs ⟨a, f⟩ ∧ ∀ i, p (f i) := by
  constructor
  · rintro ⟨y, hy⟩
    

Proof state:
case mp.intro
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
y : F (Subtype p)
hy : Subtype.val <$> y = x
⊢ ∃ a f, x = abs { fst := a, snd := f } ∧ ∀ (i : PFunctor.B (P F) a), p (f i)

Next tactic:
cases' h : repr y with a f
theorem liftp_iff {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ a f, x = abs ⟨a, f⟩ ∧ ∀ i, p (f i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    

Proof state:
case mp.intro.mk
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
y : F (Subtype p)
hy : Subtype.val <$> y = x
a : (P F).A
f : PFunctor.B (P F) a → Subtype p
h : repr y = { fst := a, snd := f }
⊢ ∃ a f, x = abs { fst := a, snd := f } ∧ ∀ (i : PFunctor.B (P F) a), p (f i)

Next tactic:
use a, fun i => (f i).val
theorem liftp_iff {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ a f, x = abs ⟨a, f⟩ ∧ ∀ i, p (f i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    use a, fun i => (f i).val
    

Proof state:
case h
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
y : F (Subtype p)
hy : Subtype.val <$> y = x
a : (P F).A
f : PFunctor.B (P F) a → Subtype p
h : repr y = { fst := a, snd := f }
⊢ x = abs { fst := a, snd := fun i => ↑(f i) } ∧ ∀ (i : PFunctor.B (P F) a), p ↑(f i)

Next tactic:
constructor
theorem liftp_iff {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ a f, x = abs ⟨a, f⟩ ∧ ∀ i, p (f i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    use a, fun i => (f i).val
    constructor
    · 

Proof state:
case h.left
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
y : F (Subtype p)
hy : Subtype.val <$> y = x
a : (P F).A
f : PFunctor.B (P F) a → Subtype p
h : repr y = { fst := a, snd := f }
⊢ x = abs { fst := a, snd := fun i => ↑(f i) }

Next tactic:
rw [← hy, ← abs_repr y, h, ← abs_map]
theorem liftp_iff {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ a f, x = abs ⟨a, f⟩ ∧ ∀ i, p (f i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    use a, fun i => (f i).val
    constructor
    · rw [← hy, ← abs_repr y, h, ← abs_map]
      

Proof state:
case h.left
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
y : F (Subtype p)
hy : Subtype.val <$> y = x
a : (P F).A
f : PFunctor.B (P F) a → Subtype p
h : repr y = { fst := a, snd := f }
⊢ abs (PFunctor.map (P F) Subtype.val { fst := a, snd := f }) = abs { fst := a, snd := fun i => ↑(f i) }

Next tactic:
rfl
theorem liftp_iff {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ a f, x = abs ⟨a, f⟩ ∧ ∀ i, p (f i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    use a, fun i => (f i).val
    constructor
    · rw [← hy, ← abs_repr y, h, ← abs_map]
      rfl
    

Proof state:
case h.right
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
y : F (Subtype p)
hy : Subtype.val <$> y = x
a : (P F).A
f : PFunctor.B (P F) a → Subtype p
h : repr y = { fst := a, snd := f }
⊢ ∀ (i : PFunctor.B (P F) a), p ↑(f i)

Next tactic:
intro i
theorem liftp_iff {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ a f, x = abs ⟨a, f⟩ ∧ ∀ i, p (f i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    use a, fun i => (f i).val
    constructor
    · rw [← hy, ← abs_repr y, h, ← abs_map]
      rfl
    intro i
    

Proof state:
case h.right
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
y : F (Subtype p)
hy : Subtype.val <$> y = x
a : (P F).A
f : PFunctor.B (P F) a → Subtype p
h : repr y = { fst := a, snd := f }
i : PFunctor.B (P F) a
⊢ p ↑(f i)

Next tactic:
apply (f i).property
theorem liftp_iff {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ a f, x = abs ⟨a, f⟩ ∧ ∀ i, p (f i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    use a, fun i => (f i).val
    constructor
    · rw [← hy, ← abs_repr y, h, ← abs_map]
      rfl
    intro i
    apply (f i).property
  

Proof state:
case mpr
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
⊢ (∃ a f, x = abs { fst := a, snd := f } ∧ ∀ (i : PFunctor.B (P F) a), p (f i)) → Liftp p x

Next tactic:
rintro ⟨a, f, h₀, h₁⟩
theorem liftp_iff {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ a f, x = abs ⟨a, f⟩ ∧ ∀ i, p (f i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    use a, fun i => (f i).val
    constructor
    · rw [← hy, ← abs_repr y, h, ← abs_map]
      rfl
    intro i
    apply (f i).property
  rintro ⟨a, f, h₀, h₁⟩
  

Proof state:
case mpr.intro.intro.intro
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
a : (P F).A
f : PFunctor.B (P F) a → α
h₀ : x = abs { fst := a, snd := f }
h₁ : ∀ (i : PFunctor.B (P F) a), p (f i)
⊢ Liftp p x

Next tactic:
use abs ⟨a, fun i => ⟨f i, h₁ i⟩⟩
theorem liftp_iff {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ a f, x = abs ⟨a, f⟩ ∧ ∀ i, p (f i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    use a, fun i => (f i).val
    constructor
    · rw [← hy, ← abs_repr y, h, ← abs_map]
      rfl
    intro i
    apply (f i).property
  rintro ⟨a, f, h₀, h₁⟩
  use abs ⟨a, fun i => ⟨f i, h₁ i⟩⟩
  

Proof state:
case h
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
a : (P F).A
f : PFunctor.B (P F) a → α
h₀ : x = abs { fst := a, snd := f }
h₁ : ∀ (i : PFunctor.B (P F) a), p (f i)
⊢ Subtype.val <$> abs { fst := a, snd := fun i => { val := f i, property := (_ : p (f i)) } } = x

Next tactic:
rw [← abs_map, h₀]
theorem liftp_iff {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ a f, x = abs ⟨a, f⟩ ∧ ∀ i, p (f i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    use a, fun i => (f i).val
    constructor
    · rw [← hy, ← abs_repr y, h, ← abs_map]
      rfl
    intro i
    apply (f i).property
  rintro ⟨a, f, h₀, h₁⟩
  use abs ⟨a, fun i => ⟨f i, h₁ i⟩⟩
  rw [← abs_map, h₀]; 

Proof state:
case h
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
a : (P F).A
f : PFunctor.B (P F) a → α
h₀ : x = abs { fst := a, snd := f }
h₁ : ∀ (i : PFunctor.B (P F) a), p (f i)
⊢ abs (PFunctor.map (P F) Subtype.val { fst := a, snd := fun i => { val := f i, property := (_ : p (f i)) } }) =
    abs { fst := a, snd := f }

Next tactic:
rfl
theorem liftp_iff' {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ u : q.P α, abs u = x ∧ ∀ i, p (u.snd i) := by
  

Proof state:
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
⊢ Liftp p x ↔ ∃ u, abs u = x ∧ ∀ (i : PFunctor.B (P F) u.fst), p (Sigma.snd u i)

Next tactic:
constructor
theorem liftp_iff' {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ u : q.P α, abs u = x ∧ ∀ i, p (u.snd i) := by
  constructor
  · 

Proof state:
case mp
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
⊢ Liftp p x → ∃ u, abs u = x ∧ ∀ (i : PFunctor.B (P F) u.fst), p (Sigma.snd u i)

Next tactic:
rintro ⟨y, hy⟩
theorem liftp_iff' {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ u : q.P α, abs u = x ∧ ∀ i, p (u.snd i) := by
  constructor
  · rintro ⟨y, hy⟩
    

Proof state:
case mp.intro
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
y : F (Subtype p)
hy : Subtype.val <$> y = x
⊢ ∃ u, abs u = x ∧ ∀ (i : PFunctor.B (P F) u.fst), p (Sigma.snd u i)

Next tactic:
cases' h : repr y with a f
theorem liftp_iff' {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ u : q.P α, abs u = x ∧ ∀ i, p (u.snd i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    

Proof state:
case mp.intro.mk
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
y : F (Subtype p)
hy : Subtype.val <$> y = x
a : (P F).A
f : PFunctor.B (P F) a → Subtype p
h : repr y = { fst := a, snd := f }
⊢ ∃ u, abs u = x ∧ ∀ (i : PFunctor.B (P F) u.fst), p (Sigma.snd u i)

Next tactic:
use ⟨a, fun i => (f i).val⟩
theorem liftp_iff' {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ u : q.P α, abs u = x ∧ ∀ i, p (u.snd i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    use ⟨a, fun i => (f i).val⟩
    

Proof state:
case h
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
y : F (Subtype p)
hy : Subtype.val <$> y = x
a : (P F).A
f : PFunctor.B (P F) a → Subtype p
h : repr y = { fst := a, snd := f }
⊢ abs { fst := a, snd := fun i => ↑(f i) } = x ∧
    ∀ (i : PFunctor.B (P F) { fst := a, snd := fun i => ↑(f i) }.fst),
      p (Sigma.snd { fst := a, snd := fun i => ↑(f i) } i)

Next tactic:
dsimp
theorem liftp_iff' {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ u : q.P α, abs u = x ∧ ∀ i, p (u.snd i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    use ⟨a, fun i => (f i).val⟩
    dsimp
    

Proof state:
case h
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
y : F (Subtype p)
hy : Subtype.val <$> y = x
a : (P F).A
f : PFunctor.B (P F) a → Subtype p
h : repr y = { fst := a, snd := f }
⊢ abs { fst := a, snd := fun i => ↑(f i) } = x ∧ ∀ (i : PFunctor.B (P F) a), p ↑(f i)

Next tactic:
constructor
theorem liftp_iff' {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ u : q.P α, abs u = x ∧ ∀ i, p (u.snd i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    use ⟨a, fun i => (f i).val⟩
    dsimp
    constructor
    · 

Proof state:
case h.left
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
y : F (Subtype p)
hy : Subtype.val <$> y = x
a : (P F).A
f : PFunctor.B (P F) a → Subtype p
h : repr y = { fst := a, snd := f }
⊢ abs { fst := a, snd := fun i => ↑(f i) } = x

Next tactic:
rw [← hy, ← abs_repr y, h, ← abs_map]
theorem liftp_iff' {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ u : q.P α, abs u = x ∧ ∀ i, p (u.snd i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    use ⟨a, fun i => (f i).val⟩
    dsimp
    constructor
    · rw [← hy, ← abs_repr y, h, ← abs_map]
      

Proof state:
case h.left
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
y : F (Subtype p)
hy : Subtype.val <$> y = x
a : (P F).A
f : PFunctor.B (P F) a → Subtype p
h : repr y = { fst := a, snd := f }
⊢ abs { fst := a, snd := fun i => ↑(f i) } = abs (PFunctor.map (P F) Subtype.val { fst := a, snd := f })

Next tactic:
rfl
theorem liftp_iff' {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ u : q.P α, abs u = x ∧ ∀ i, p (u.snd i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    use ⟨a, fun i => (f i).val⟩
    dsimp
    constructor
    · rw [← hy, ← abs_repr y, h, ← abs_map]
      rfl
    

Proof state:
case h.right
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
y : F (Subtype p)
hy : Subtype.val <$> y = x
a : (P F).A
f : PFunctor.B (P F) a → Subtype p
h : repr y = { fst := a, snd := f }
⊢ ∀ (i : PFunctor.B (P F) a), p ↑(f i)

Next tactic:
intro i
theorem liftp_iff' {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ u : q.P α, abs u = x ∧ ∀ i, p (u.snd i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    use ⟨a, fun i => (f i).val⟩
    dsimp
    constructor
    · rw [← hy, ← abs_repr y, h, ← abs_map]
      rfl
    intro i
    

Proof state:
case h.right
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
y : F (Subtype p)
hy : Subtype.val <$> y = x
a : (P F).A
f : PFunctor.B (P F) a → Subtype p
h : repr y = { fst := a, snd := f }
i : PFunctor.B (P F) a
⊢ p ↑(f i)

Next tactic:
apply (f i).property
theorem liftp_iff' {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ u : q.P α, abs u = x ∧ ∀ i, p (u.snd i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    use ⟨a, fun i => (f i).val⟩
    dsimp
    constructor
    · rw [← hy, ← abs_repr y, h, ← abs_map]
      rfl
    intro i
    apply (f i).property
  

Proof state:
case mpr
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
⊢ (∃ u, abs u = x ∧ ∀ (i : PFunctor.B (P F) u.fst), p (Sigma.snd u i)) → Liftp p x

Next tactic:
rintro ⟨⟨a, f⟩, h₀, h₁⟩
theorem liftp_iff' {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ u : q.P α, abs u = x ∧ ∀ i, p (u.snd i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    use ⟨a, fun i => (f i).val⟩
    dsimp
    constructor
    · rw [← hy, ← abs_repr y, h, ← abs_map]
      rfl
    intro i
    apply (f i).property
  rintro ⟨⟨a, f⟩, h₀, h₁⟩; 

Proof state:
case mpr.intro.mk.intro
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
a : (P F).A
f : PFunctor.B (P F) a → α
h₀ : abs { fst := a, snd := f } = x
h₁ : ∀ (i : PFunctor.B (P F) { fst := a, snd := f }.fst), p (Sigma.snd { fst := a, snd := f } i)
⊢ Liftp p x

Next tactic:
dsimp at *
theorem liftp_iff' {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ u : q.P α, abs u = x ∧ ∀ i, p (u.snd i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    use ⟨a, fun i => (f i).val⟩
    dsimp
    constructor
    · rw [← hy, ← abs_repr y, h, ← abs_map]
      rfl
    intro i
    apply (f i).property
  rintro ⟨⟨a, f⟩, h₀, h₁⟩; dsimp at *
  

Proof state:
case mpr.intro.mk.intro
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
a : (P F).A
f : PFunctor.B (P F) a → α
h₀ : abs { fst := a, snd := f } = x
h₁ : ∀ (i : PFunctor.B (P F) a), p (f i)
⊢ Liftp p x

Next tactic:
use abs ⟨a, fun i => ⟨f i, h₁ i⟩⟩
theorem liftp_iff' {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ u : q.P α, abs u = x ∧ ∀ i, p (u.snd i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    use ⟨a, fun i => (f i).val⟩
    dsimp
    constructor
    · rw [← hy, ← abs_repr y, h, ← abs_map]
      rfl
    intro i
    apply (f i).property
  rintro ⟨⟨a, f⟩, h₀, h₁⟩; dsimp at *
  use abs ⟨a, fun i => ⟨f i, h₁ i⟩⟩
  

Proof state:
case h
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
a : (P F).A
f : PFunctor.B (P F) a → α
h₀ : abs { fst := a, snd := f } = x
h₁ : ∀ (i : PFunctor.B (P F) a), p (f i)
⊢ Subtype.val <$> abs { fst := a, snd := fun i => { val := f i, property := (_ : p (f i)) } } = x

Next tactic:
rw [← abs_map, ← h₀]
theorem liftp_iff' {α : Type u} (p : α → Prop) (x : F α) :
    Liftp p x ↔ ∃ u : q.P α, abs u = x ∧ ∀ i, p (u.snd i) := by
  constructor
  · rintro ⟨y, hy⟩
    cases' h : repr y with a f
    use ⟨a, fun i => (f i).val⟩
    dsimp
    constructor
    · rw [← hy, ← abs_repr y, h, ← abs_map]
      rfl
    intro i
    apply (f i).property
  rintro ⟨⟨a, f⟩, h₀, h₁⟩; dsimp at *
  use abs ⟨a, fun i => ⟨f i, h₁ i⟩⟩
  rw [← abs_map, ← h₀]; 

Proof state:
case h
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
p : α → Prop
x : F α
a : (P F).A
f : PFunctor.B (P F) a → α
h₀ : abs { fst := a, snd := f } = x
h₁ : ∀ (i : PFunctor.B (P F) a), p (f i)
⊢ abs (PFunctor.map (P F) Subtype.val { fst := a, snd := fun i => { val := f i, property := (_ : p (f i)) } }) =
    abs { fst := a, snd := f }

Next tactic:
rfl
theorem liftr_iff {α : Type u} (r : α → α → Prop) (x y : F α) :
    Liftr r x y ↔ ∃ a f₀ f₁, x = abs ⟨a, f₀⟩ ∧ y = abs ⟨a, f₁⟩ ∧ ∀ i, r (f₀ i) (f₁ i) := by
  

Proof state:
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
r : α → α → Prop
x y : F α
⊢ Liftr r x y ↔
    ∃ a f₀ f₁,
      x = abs { fst := a, snd := f₀ } ∧ y = abs { fst := a, snd := f₁ } ∧ ∀ (i : PFunctor.B (P F) a), r (f₀ i) (f₁ i)

Next tactic:
constructor
theorem liftr_iff {α : Type u} (r : α → α → Prop) (x y : F α) :
    Liftr r x y ↔ ∃ a f₀ f₁, x = abs ⟨a, f₀⟩ ∧ y = abs ⟨a, f₁⟩ ∧ ∀ i, r (f₀ i) (f₁ i) := by
  constructor
  · 

Proof state:
case mp
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
r : α → α → Prop
x y : F α
⊢ Liftr r x y →
    ∃ a f₀ f₁,
      x = abs { fst := a, snd := f₀ } ∧ y = abs { fst := a, snd := f₁ } ∧ ∀ (i : PFunctor.B (P F) a), r (f₀ i) (f₁ i)

Next tactic:
rintro ⟨u, xeq, yeq⟩
theorem liftr_iff {α : Type u} (r : α → α → Prop) (x y : F α) :
    Liftr r x y ↔ ∃ a f₀ f₁, x = abs ⟨a, f₀⟩ ∧ y = abs ⟨a, f₁⟩ ∧ ∀ i, r (f₀ i) (f₁ i) := by
  constructor
  · rintro ⟨u, xeq, yeq⟩
    

Proof state:
case mp.intro.intro
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
r : α → α → Prop
x y : F α
u : F { p // r p.1 p.2 }
xeq : (fun t => (↑t).1) <$> u = x
yeq : (fun t => (↑t).2) <$> u = y
⊢ ∃ a f₀ f₁,
    x = abs { fst := a, snd := f₀ } ∧ y = abs { fst := a, snd := f₁ } ∧ ∀ (i : PFunctor.B (P F) a), r (f₀ i) (f₁ i)

Next tactic:
cases' h : repr u with a f
theorem liftr_iff {α : Type u} (r : α → α → Prop) (x y : F α) :
    Liftr r x y ↔ ∃ a f₀ f₁, x = abs ⟨a, f₀⟩ ∧ y = abs ⟨a, f₁⟩ ∧ ∀ i, r (f₀ i) (f₁ i) := by
  constructor
  · rintro ⟨u, xeq, yeq⟩
    cases' h : repr u with a f
    

Proof state:
case mp.intro.intro.mk
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
r : α → α → Prop
x y : F α
u : F { p // r p.1 p.2 }
xeq : (fun t => (↑t).1) <$> u = x
yeq : (fun t => (↑t).2) <$> u = y
a : (P F).A
f : PFunctor.B (P F) a → { p // r p.1 p.2 }
h : repr u = { fst := a, snd := f }
⊢ ∃ a f₀ f₁,
    x = abs { fst := a, snd := f₀ } ∧ y = abs { fst := a, snd := f₁ } ∧ ∀ (i : PFunctor.B (P F) a), r (f₀ i) (f₁ i)

Next tactic:
use a, fun i => (f i).val.fst, fun i => (f i).val.snd
theorem liftr_iff {α : Type u} (r : α → α → Prop) (x y : F α) :
    Liftr r x y ↔ ∃ a f₀ f₁, x = abs ⟨a, f₀⟩ ∧ y = abs ⟨a, f₁⟩ ∧ ∀ i, r (f₀ i) (f₁ i) := by
  constructor
  · rintro ⟨u, xeq, yeq⟩
    cases' h : repr u with a f
    use a, fun i => (f i).val.fst, fun i => (f i).val.snd
    

Proof state:
case h
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
r : α → α → Prop
x y : F α
u : F { p // r p.1 p.2 }
xeq : (fun t => (↑t).1) <$> u = x
yeq : (fun t => (↑t).2) <$> u = y
a : (P F).A
f : PFunctor.B (P F) a → { p // r p.1 p.2 }
h : repr u = { fst := a, snd := f }
⊢ x = abs { fst := a, snd := fun i => (↑(f i)).1 } ∧
    y = abs { fst := a, snd := fun i => (↑(f i)).2 } ∧ ∀ (i : PFunctor.B (P F) a), r (↑(f i)).1 (↑(f i)).2

Next tactic:
constructor
theorem liftr_iff {α : Type u} (r : α → α → Prop) (x y : F α) :
    Liftr r x y ↔ ∃ a f₀ f₁, x = abs ⟨a, f₀⟩ ∧ y = abs ⟨a, f₁⟩ ∧ ∀ i, r (f₀ i) (f₁ i) := by
  constructor
  · rintro ⟨u, xeq, yeq⟩
    cases' h : repr u with a f
    use a, fun i => (f i).val.fst, fun i => (f i).val.snd
    constructor
    · 

Proof state:
case h.left
F : Type u → Type u
inst✝ : Functor F
q : QPF F
α : Type u
r : α → α → Prop
x y : F α
u : F { p // r p.1 p.2 }
xeq : (fun t => (↑t).1) <$> u = x
yeq : (fun t => (↑t).2) <$> u = y
a : (P F).A
f : PFunctor.B (P F) a → { p // r p.1 p.2 }
h : repr u = { fst := a, snd := f }
⊢ x = abs { fst := a, snd := fun i => (↑(f i)).1 }

Next tactic:
rw [← xeq, ← abs_repr u, h, ← abs_map]