l3lab/ntp-mathlib huggingface dataset:
theorem nat_strong_rec (f : α → ℕ → σ) {g : α → List σ → Option σ} (hg : Computable₂ g)
    (H : ∀ a n, g a ((List.range n).map (f a)) = Option.some (f a n)) : Computable₂ f :=
  suffices Computable₂ fun a n => (List.range n).map (f a) from
    option_some_iff.1 <|
      (list_get?.comp (this.comp fst (succ.comp snd)) snd).to₂.of_eq fun a => by
        simp [List.get?_range (Nat.lt_succ_self a.2)]
  option_some_iff.1 <|
    (nat_rec snd (const (Option.some []))
          (to₂ <|
            option_bind (snd.comp snd) <|
              to₂ <|
                option_map (hg.comp (fst.comp <| fst.comp fst) snd)
                  (to₂ <| list_concat.comp (snd.comp fst) snd))).of_eq
      fun a => by
      simp; 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → ℕ → σ
g : α → List σ → Option σ
hg : Computable₂ g
H : ∀ (a : α) (n : ℕ), g a (List.map (f a) (List.range n)) = Option.some (f a n)
a : α × ℕ
⊢ Nat.rec (Option.some []) (fun y IH => Option.bind IH fun b => Option.map (fun b_1 => b ++ [b_1]) (g a.1 b)) a.2 =
    Option.some (List.map (f a.1) (List.range a.2))

Next tactic:
induction' a.2 with n IH
theorem nat_strong_rec (f : α → ℕ → σ) {g : α → List σ → Option σ} (hg : Computable₂ g)
    (H : ∀ a n, g a ((List.range n).map (f a)) = Option.some (f a n)) : Computable₂ f :=
  suffices Computable₂ fun a n => (List.range n).map (f a) from
    option_some_iff.1 <|
      (list_get?.comp (this.comp fst (succ.comp snd)) snd).to₂.of_eq fun a => by
        simp [List.get?_range (Nat.lt_succ_self a.2)]
  option_some_iff.1 <|
    (nat_rec snd (const (Option.some []))
          (to₂ <|
            option_bind (snd.comp snd) <|
              to₂ <|
                option_map (hg.comp (fst.comp <| fst.comp fst) snd)
                  (to₂ <| list_concat.comp (snd.comp fst) snd))).of_eq
      fun a => by
      simp; induction' a.2 with n IH; · 

Proof state:
case zero
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → ℕ → σ
g : α → List σ → Option σ
hg : Computable₂ g
H : ∀ (a : α) (n : ℕ), g a (List.map (f a) (List.range n)) = Option.some (f a n)
a : α × ℕ
⊢ Nat.rec (Option.some []) (fun y IH => Option.bind IH fun b => Option.map (fun b_1 => b ++ [b_1]) (g a.1 b)) Nat.zero =
    Option.some (List.map (f a.1) (List.range Nat.zero))

Next tactic:
rfl
theorem nat_strong_rec (f : α → ℕ → σ) {g : α → List σ → Option σ} (hg : Computable₂ g)
    (H : ∀ a n, g a ((List.range n).map (f a)) = Option.some (f a n)) : Computable₂ f :=
  suffices Computable₂ fun a n => (List.range n).map (f a) from
    option_some_iff.1 <|
      (list_get?.comp (this.comp fst (succ.comp snd)) snd).to₂.of_eq fun a => by
        simp [List.get?_range (Nat.lt_succ_self a.2)]
  option_some_iff.1 <|
    (nat_rec snd (const (Option.some []))
          (to₂ <|
            option_bind (snd.comp snd) <|
              to₂ <|
                option_map (hg.comp (fst.comp <| fst.comp fst) snd)
                  (to₂ <| list_concat.comp (snd.comp fst) snd))).of_eq
      fun a => by
      simp; induction' a.2 with n IH; · rfl
      

Proof state:
case succ
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → ℕ → σ
g : α → List σ → Option σ
hg : Computable₂ g
H : ∀ (a : α) (n : ℕ), g a (List.map (f a) (List.range n)) = Option.some (f a n)
a : α × ℕ
n : ℕ
IH :
  Nat.rec (Option.some []) (fun y IH => Option.bind IH fun b => Option.map (fun b_1 => b ++ [b_1]) (g a.1 b)) n =
    Option.some (List.map (f a.1) (List.range n))
⊢ Nat.rec (Option.some []) (fun y IH => Option.bind IH fun b => Option.map (fun b_1 => b ++ [b_1]) (g a.1 b))
      (Nat.succ n) =
    Option.some (List.map (f a.1) (List.range (Nat.succ n)))

Next tactic:
simp [IH, H, List.range_succ]
theorem nat_strong_rec (f : α → ℕ → σ) {g : α → List σ → Option σ} (hg : Computable₂ g)
    (H : ∀ a n, g a ((List.range n).map (f a)) = Option.some (f a n)) : Computable₂ f :=
  suffices Computable₂ fun a n => (List.range n).map (f a) from
    option_some_iff.1 <|
      (list_get?.comp (this.comp fst (succ.comp snd)) snd).to₂.of_eq fun a => by
        

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → ℕ → σ
g : α → List σ → Option σ
hg : Computable₂ g
H : ∀ (a : α) (n : ℕ), g a (List.map (f a) (List.range n)) = Option.some (f a n)
this : Computable₂ fun a n => List.map (f a) (List.range n)
a : α × ℕ
⊢ (fun a b => List.get? (List.map (f (a, b).1) (List.range (Nat.succ (a, b).2))) (a, b).2) a.1 a.2 =
    Option.some (f a.1 a.2)

Next tactic:
simp [List.get?_range (Nat.lt_succ_self a.2)]
theorem list_ofFn :
    ∀ {n} {f : Fin n → α → σ},
      (∀ i, Computable (f i)) → Computable fun a => List.ofFn fun i => f i a
  | 0, _, _ => const []
  | n + 1, f, hf => by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
n : ℕ
f : Fin (n + 1) → α → σ
hf : ∀ (i : Fin (n + 1)), Computable (f i)
⊢ Computable fun a => List.ofFn fun i => f i a

Next tactic:
simp only [List.ofFn_succ]
theorem list_ofFn :
    ∀ {n} {f : Fin n → α → σ},
      (∀ i, Computable (f i)) → Computable fun a => List.ofFn fun i => f i a
  | 0, _, _ => const []
  | n + 1, f, hf => by
    simp only [List.ofFn_succ]
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
n : ℕ
f : Fin (n + 1) → α → σ
hf : ∀ (i : Fin (n + 1)), Computable (f i)
⊢ Computable fun a => f 0 a :: List.ofFn fun i => f (Fin.succ i) a

Next tactic:
exact list_cons.comp (hf 0) (list_ofFn fun i => hf i.succ)
theorem vector_ofFn {n} {f : Fin n → α → σ} (hf : ∀ i, Computable (f i)) :
    Computable fun a => Vector.ofFn fun i => f i a :=
  (Partrec.vector_mOfFn hf).of_eq fun a => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
n : ℕ
f : Fin n → α → σ
hf : ∀ (i : Fin n), Computable (f i)
a : α
⊢ (Vector.mOfFn fun i => ↑(f i) a) = (↑fun a => Vector.ofFn fun i => f i a) a

Next tactic:
simp
theorem option_some_iff {f : α →. σ} : (Partrec fun a => (f a).map Option.some) ↔ Partrec f :=
  ⟨fun h => (Nat.Partrec.ppred.comp h).of_eq fun n => by
      -- Porting note: needed to help with applying bind_some_eq_map because `Function.comp` got
      -- less reducible.
      

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α →. σ
h : Partrec fun a => Part.map Option.some (f a)
n : ℕ
⊢ (do
      let n ← Part.bind ↑(decode n) fun a => Part.map encode ((fun a => Part.map Option.some (f a)) a)
      ↑(Nat.ppred n)) =
    Part.bind ↑(decode n) fun a => Part.map encode (f a)

Next tactic:
simp [Part.bind_assoc, ← Function.comp_apply (f := Part.some) (g := encode), bind_some_eq_map,
        -Function.comp_apply]
theorem option_casesOn_right {o : α → Option β} {f : α → σ} {g : α → β →. σ} (ho : Computable o)
    (hf : Computable f) (hg : Partrec₂ g) :
    @Partrec _ σ _ _ fun a => Option.casesOn (o a) (Part.some (f a)) (g a) :=
  have :
    Partrec fun a : α =>
      Nat.casesOn (encode (o a)) (Part.some (f a)) (fun n => Part.bind (decode (α := β) n) (g a)) :=
    nat_casesOn_right (h := fun a n ↦ Part.bind (ofOption (decode n)) fun b ↦ g a b)
      (encode_iff.2 ho) hf.partrec <|
        ((@Computable.decode β _).comp snd).ofOption.bind (hg.comp (fst.comp fst) snd).to₂
  this.of_eq fun a => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
o : α → Option β
f : α → σ
g : α → β →. σ
ho : Computable o
hf : Computable f
hg : Partrec₂ g
this : Partrec fun a => Nat.casesOn (encode (o a)) (Part.some (f a)) fun n => Part.bind (↑(decode n)) (g a)
a : α
⊢ (Nat.casesOn (encode (o a)) (Part.some (f a)) fun n => Part.bind (↑(decode n)) (g a)) =
    Option.casesOn (o a) (Part.some (f a)) (g a)

Next tactic:
cases' o a with b
theorem option_casesOn_right {o : α → Option β} {f : α → σ} {g : α → β →. σ} (ho : Computable o)
    (hf : Computable f) (hg : Partrec₂ g) :
    @Partrec _ σ _ _ fun a => Option.casesOn (o a) (Part.some (f a)) (g a) :=
  have :
    Partrec fun a : α =>
      Nat.casesOn (encode (o a)) (Part.some (f a)) (fun n => Part.bind (decode (α := β) n) (g a)) :=
    nat_casesOn_right (h := fun a n ↦ Part.bind (ofOption (decode n)) fun b ↦ g a b)
      (encode_iff.2 ho) hf.partrec <|
        ((@Computable.decode β _).comp snd).ofOption.bind (hg.comp (fst.comp fst) snd).to₂
  this.of_eq fun a => by cases' o a with b <;> 

Proof state:
case none
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
o : α → Option β
f : α → σ
g : α → β →. σ
ho : Computable o
hf : Computable f
hg : Partrec₂ g
this : Partrec fun a => Nat.casesOn (encode (o a)) (Part.some (f a)) fun n => Part.bind (↑(decode n)) (g a)
a : α
⊢ (Nat.casesOn (encode Option.none) (Part.some (f a)) fun n => Part.bind (↑(decode n)) (g a)) =
    Option.casesOn Option.none (Part.some (f a)) (g a)

Next tactic:
simp [encodek]
theorem option_casesOn_right {o : α → Option β} {f : α → σ} {g : α → β →. σ} (ho : Computable o)
    (hf : Computable f) (hg : Partrec₂ g) :
    @Partrec _ σ _ _ fun a => Option.casesOn (o a) (Part.some (f a)) (g a) :=
  have :
    Partrec fun a : α =>
      Nat.casesOn (encode (o a)) (Part.some (f a)) (fun n => Part.bind (decode (α := β) n) (g a)) :=
    nat_casesOn_right (h := fun a n ↦ Part.bind (ofOption (decode n)) fun b ↦ g a b)
      (encode_iff.2 ho) hf.partrec <|
        ((@Computable.decode β _).comp snd).ofOption.bind (hg.comp (fst.comp fst) snd).to₂
  this.of_eq fun a => by cases' o a with b <;> 

Proof state:
case some
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
o : α → Option β
f : α → σ
g : α → β →. σ
ho : Computable o
hf : Computable f
hg : Partrec₂ g
this : Partrec fun a => Nat.casesOn (encode (o a)) (Part.some (f a)) fun n => Part.bind (↑(decode n)) (g a)
a : α
b : β
⊢ (Nat.casesOn (encode (Option.some b)) (Part.some (f a)) fun n => Part.bind (↑(decode n)) (g a)) =
    Option.casesOn (Option.some b) (Part.some (f a)) (g a)

Next tactic:
simp [encodek]
theorem sum_casesOn_right {f : α → Sum β γ} {g : α → β → σ} {h : α → γ →. σ} (hf : Computable f)
    (hg : Computable₂ g) (hh : Partrec₂ h) :
    @Partrec _ σ _ _ fun a => Sum.casesOn (f a) (fun b => Part.some (g a b)) (h a) :=
  have :
    Partrec fun a =>
      (Option.casesOn (Sum.casesOn (f a) (fun _ => Option.none) Option.some : Option γ)
          (some (Sum.casesOn (f a) (fun b => some (g a b)) fun _ => Option.none)) fun c =>
          (h a c).map Option.some :
        Part (Option σ)) :=
    option_casesOn_right (g := fun a n => Part.map Option.some (h a n))
      (sum_casesOn hf (const Option.none).to₂ (option_some.comp snd).to₂)
      (sum_casesOn (g := fun a n => Option.some (g a n)) hf (option_some.comp hg)
        (const Option.none).to₂)
      (option_some_iff.2 hh)
  option_some_iff.1 <| this.of_eq fun a => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → β ⊕ γ
g : α → β → σ
h : α → γ →. σ
hf : Computable f
hg : Computable₂ g
hh : Partrec₂ h
this :
  Partrec fun a =>
    Option.casesOn (Sum.casesOn (f a) (fun x => Option.none) Option.some)
      (Part.some (Sum.casesOn (f a) (fun b => Option.some (g a b)) fun x => Option.none)) fun c =>
      Part.map Option.some (h a c)
a : α
⊢ (Option.casesOn (Sum.casesOn (f a) (fun x => Option.none) Option.some)
      (Part.some (Sum.casesOn (f a) (fun b => Option.some (g a b)) fun x => Option.none)) fun c =>
      Part.map Option.some (h a c)) =
    Part.map Option.some (Sum.casesOn (f a) (fun b => Part.some (g a b)) (h a))

Next tactic:
cases f a
theorem sum_casesOn_right {f : α → Sum β γ} {g : α → β → σ} {h : α → γ →. σ} (hf : Computable f)
    (hg : Computable₂ g) (hh : Partrec₂ h) :
    @Partrec _ σ _ _ fun a => Sum.casesOn (f a) (fun b => Part.some (g a b)) (h a) :=
  have :
    Partrec fun a =>
      (Option.casesOn (Sum.casesOn (f a) (fun _ => Option.none) Option.some : Option γ)
          (some (Sum.casesOn (f a) (fun b => some (g a b)) fun _ => Option.none)) fun c =>
          (h a c).map Option.some :
        Part (Option σ)) :=
    option_casesOn_right (g := fun a n => Part.map Option.some (h a n))
      (sum_casesOn hf (const Option.none).to₂ (option_some.comp snd).to₂)
      (sum_casesOn (g := fun a n => Option.some (g a n)) hf (option_some.comp hg)
        (const Option.none).to₂)
      (option_some_iff.2 hh)
  option_some_iff.1 <| this.of_eq fun a => by cases f a <;> 

Proof state:
case inl
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → β ⊕ γ
g : α → β → σ
h : α → γ →. σ
hf : Computable f
hg : Computable₂ g
hh : Partrec₂ h
this :
  Partrec fun a =>
    Option.casesOn (Sum.casesOn (f a) (fun x => Option.none) Option.some)
      (Part.some (Sum.casesOn (f a) (fun b => Option.some (g a b)) fun x => Option.none)) fun c =>
      Part.map Option.some (h a c)
a : α
val✝ : β
⊢ (Option.casesOn (Sum.casesOn (Sum.inl val✝) (fun x => Option.none) Option.some)
      (Part.some (Sum.casesOn (Sum.inl val✝) (fun b => Option.some (g a b)) fun x => Option.none)) fun c =>
      Part.map Option.some (h a c)) =
    Part.map Option.some (Sum.casesOn (Sum.inl val✝) (fun b => Part.some (g a b)) (h a))

Next tactic:
simp
theorem sum_casesOn_right {f : α → Sum β γ} {g : α → β → σ} {h : α → γ →. σ} (hf : Computable f)
    (hg : Computable₂ g) (hh : Partrec₂ h) :
    @Partrec _ σ _ _ fun a => Sum.casesOn (f a) (fun b => Part.some (g a b)) (h a) :=
  have :
    Partrec fun a =>
      (Option.casesOn (Sum.casesOn (f a) (fun _ => Option.none) Option.some : Option γ)
          (some (Sum.casesOn (f a) (fun b => some (g a b)) fun _ => Option.none)) fun c =>
          (h a c).map Option.some :
        Part (Option σ)) :=
    option_casesOn_right (g := fun a n => Part.map Option.some (h a n))
      (sum_casesOn hf (const Option.none).to₂ (option_some.comp snd).to₂)
      (sum_casesOn (g := fun a n => Option.some (g a n)) hf (option_some.comp hg)
        (const Option.none).to₂)
      (option_some_iff.2 hh)
  option_some_iff.1 <| this.of_eq fun a => by cases f a <;> 

Proof state:
case inr
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → β ⊕ γ
g : α → β → σ
h : α → γ →. σ
hf : Computable f
hg : Computable₂ g
hh : Partrec₂ h
this :
  Partrec fun a =>
    Option.casesOn (Sum.casesOn (f a) (fun x => Option.none) Option.some)
      (Part.some (Sum.casesOn (f a) (fun b => Option.some (g a b)) fun x => Option.none)) fun c =>
      Part.map Option.some (h a c)
a : α
val✝ : γ
⊢ (Option.casesOn (Sum.casesOn (Sum.inr val✝) (fun x => Option.none) Option.some)
      (Part.some (Sum.casesOn (Sum.inr val✝) (fun b => Option.some (g a b)) fun x => Option.none)) fun c =>
      Part.map Option.some (h a c)) =
    Part.map Option.some (Sum.casesOn (Sum.inr val✝) (fun b => Part.some (g a b)) (h a))

Next tactic:
simp
theorem sum_casesOn_left {f : α → Sum β γ} {g : α → β →. σ} {h : α → γ → σ} (hf : Computable f)
    (hg : Partrec₂ g) (hh : Computable₂ h) :
    @Partrec _ σ _ _ fun a => Sum.casesOn (f a) (g a) fun c => Part.some (h a c) :=
  (sum_casesOn_right (sum_casesOn hf (sum_inr.comp snd).to₂ (sum_inl.comp snd).to₂) hh hg).of_eq
    fun a => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → β ⊕ γ
g : α → β →. σ
h : α → γ → σ
hf : Computable f
hg : Partrec₂ g
hh : Computable₂ h
a : α
⊢ Sum.casesOn (Sum.casesOn (f a) (fun b => Sum.inr (a, b).2) fun b => Sum.inl (a, b).2) (fun b => Part.some (h a b))
      (g a) =
    Sum.casesOn (f a) (g a) fun c => Part.some (h a c)

Next tactic:
cases f a
theorem sum_casesOn_left {f : α → Sum β γ} {g : α → β →. σ} {h : α → γ → σ} (hf : Computable f)
    (hg : Partrec₂ g) (hh : Computable₂ h) :
    @Partrec _ σ _ _ fun a => Sum.casesOn (f a) (g a) fun c => Part.some (h a c) :=
  (sum_casesOn_right (sum_casesOn hf (sum_inr.comp snd).to₂ (sum_inl.comp snd).to₂) hh hg).of_eq
    fun a => by cases f a <;> 

Proof state:
case inl
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → β ⊕ γ
g : α → β →. σ
h : α → γ → σ
hf : Computable f
hg : Partrec₂ g
hh : Computable₂ h
a : α
val✝ : β
⊢ Sum.casesOn (Sum.casesOn (Sum.inl val✝) (fun b => Sum.inr (a, b).2) fun b => Sum.inl (a, b).2)
      (fun b => Part.some (h a b)) (g a) =
    Sum.casesOn (Sum.inl val✝) (g a) fun c => Part.some (h a c)

Next tactic:
simp
theorem sum_casesOn_left {f : α → Sum β γ} {g : α → β →. σ} {h : α → γ → σ} (hf : Computable f)
    (hg : Partrec₂ g) (hh : Computable₂ h) :
    @Partrec _ σ _ _ fun a => Sum.casesOn (f a) (g a) fun c => Part.some (h a c) :=
  (sum_casesOn_right (sum_casesOn hf (sum_inr.comp snd).to₂ (sum_inl.comp snd).to₂) hh hg).of_eq
    fun a => by cases f a <;> 

Proof state:
case inr
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → β ⊕ γ
g : α → β →. σ
h : α → γ → σ
hf : Computable f
hg : Partrec₂ g
hh : Computable₂ h
a : α
val✝ : γ
⊢ Sum.casesOn (Sum.casesOn (Sum.inr val✝) (fun b => Sum.inr (a, b).2) fun b => Sum.inl (a, b).2)
      (fun b => Part.some (h a b)) (g a) =
    Sum.casesOn (Sum.inr val✝) (g a) fun c => Part.some (h a c)

Next tactic:
simp
theorem fix_aux {α σ} (f : α →. Sum σ α) (a : α) (b : σ) :
    let F : α → ℕ →. Sum σ α := fun a n =>
      n.rec (some (Sum.inr a)) fun _ IH => IH.bind fun s => Sum.casesOn s (fun _ => Part.some s) f
    (∃ n : ℕ,
        ((∃ b' : σ, Sum.inl b' ∈ F a n) ∧ ∀ {m : ℕ}, m < n → ∃ b : α, Sum.inr b ∈ F a m) ∧
          Sum.inl b ∈ F a n) ↔
      b ∈ PFun.fix f a := by
  

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
σ✝ : Type u_4
inst✝³ : Primcodable α✝
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ✝
α : Type u_5
σ : Type u_6
f : α →. σ ⊕ α
a : α
b : σ
⊢ let F := fun a n =>
    Nat.rec (Part.some (Sum.inr a)) (fun x IH => Part.bind IH fun s => Sum.casesOn s (fun x => Part.some s) f) n;
  (∃ n, ((∃ b', Sum.inl b' ∈ F a n) ∧ ∀ {m : ℕ}, m < n → ∃ b, Sum.inr b ∈ F a m) ∧ Sum.inl b ∈ F a n) ↔ b ∈ PFun.fix f a

Next tactic:
intro F
theorem fix_aux {α σ} (f : α →. Sum σ α) (a : α) (b : σ) :
    let F : α → ℕ →. Sum σ α := fun a n =>
      n.rec (some (Sum.inr a)) fun _ IH => IH.bind fun s => Sum.casesOn s (fun _ => Part.some s) f
    (∃ n : ℕ,
        ((∃ b' : σ, Sum.inl b' ∈ F a n) ∧ ∀ {m : ℕ}, m < n → ∃ b : α, Sum.inr b ∈ F a m) ∧
          Sum.inl b ∈ F a n) ↔
      b ∈ PFun.fix f a := by
  intro F; 

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
σ✝ : Type u_4
inst✝³ : Primcodable α✝
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ✝
α : Type u_5
σ : Type u_6
f : α →. σ ⊕ α
a : α
b : σ
F : α → ℕ →. σ ⊕ α :=
  fun a n =>
    Nat.rec (Part.some (Sum.inr a)) (fun x IH => Part.bind IH fun s => Sum.casesOn s (fun x => Part.some s) f) n
⊢ (∃ n, ((∃ b', Sum.inl b' ∈ F a n) ∧ ∀ {m : ℕ}, m < n → ∃ b, Sum.inr b ∈ F a m) ∧ Sum.inl b ∈ F a n) ↔ b ∈ PFun.fix f a

Next tactic:
refine' ⟨fun h => _, fun h => _⟩
theorem fix_aux {α σ} (f : α →. Sum σ α) (a : α) (b : σ) :
    let F : α → ℕ →. Sum σ α := fun a n =>
      n.rec (some (Sum.inr a)) fun _ IH => IH.bind fun s => Sum.casesOn s (fun _ => Part.some s) f
    (∃ n : ℕ,
        ((∃ b' : σ, Sum.inl b' ∈ F a n) ∧ ∀ {m : ℕ}, m < n → ∃ b : α, Sum.inr b ∈ F a m) ∧
          Sum.inl b ∈ F a n) ↔
      b ∈ PFun.fix f a := by
  intro F; refine' ⟨fun h => _, fun h => _⟩
  · 

Proof state:
case refine'_1
α✝ : Type u_1
β : Type u_2
γ : Type u_3
σ✝ : Type u_4
inst✝³ : Primcodable α✝
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ✝
α : Type u_5
σ : Type u_6
f : α →. σ ⊕ α
a : α
b : σ
F : α → ℕ →. σ ⊕ α :=
  fun a n =>
    Nat.rec (Part.some (Sum.inr a)) (fun x IH => Part.bind IH fun s => Sum.casesOn s (fun x => Part.some s) f) n
h : ∃ n, ((∃ b', Sum.inl b' ∈ F a n) ∧ ∀ {m : ℕ}, m < n → ∃ b, Sum.inr b ∈ F a m) ∧ Sum.inl b ∈ F a n
⊢ b ∈ PFun.fix f a

Next tactic:
rcases h with ⟨n, ⟨_x, h₁⟩, h₂⟩
theorem fix_aux {α σ} (f : α →. Sum σ α) (a : α) (b : σ) :
    let F : α → ℕ →. Sum σ α := fun a n =>
      n.rec (some (Sum.inr a)) fun _ IH => IH.bind fun s => Sum.casesOn s (fun _ => Part.some s) f
    (∃ n : ℕ,
        ((∃ b' : σ, Sum.inl b' ∈ F a n) ∧ ∀ {m : ℕ}, m < n → ∃ b : α, Sum.inr b ∈ F a m) ∧
          Sum.inl b ∈ F a n) ↔
      b ∈ PFun.fix f a := by
  intro F; refine' ⟨fun h => _, fun h => _⟩
  · rcases h with ⟨n, ⟨_x, h₁⟩, h₂⟩
    

Proof state:
case refine'_1.intro.intro.intro
α✝ : Type u_1
β : Type u_2
γ : Type u_3
σ✝ : Type u_4
inst✝³ : Primcodable α✝
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ✝
α : Type u_5
σ : Type u_6
f : α →. σ ⊕ α
a : α
b : σ
F : α → ℕ →. σ ⊕ α :=
  fun a n =>
    Nat.rec (Part.some (Sum.inr a)) (fun x IH => Part.bind IH fun s => Sum.casesOn s (fun x => Part.some s) f) n
n : ℕ
h₂ : Sum.inl b ∈ F a n
_x : ∃ b', Sum.inl b' ∈ F a n
h₁ : ∀ {m : ℕ}, m < n → ∃ b, Sum.inr b ∈ F a m
⊢ b ∈ PFun.fix f a

Next tactic:
have : ∀ m a', Sum.inr a' ∈ F a m → b ∈ PFun.fix f a' → b ∈ PFun.fix f a := by
      intro m a' am ba
      induction' m with m IH generalizing a' <;> simp at am
      · rwa [← am]
      rcases am with ⟨a₂, am₂, fa₂⟩
      exact IH _ am₂ (PFun.mem_fix_iff.2 (Or.inr ⟨_, fa₂, ba⟩))
theorem fix_aux {α σ} (f : α →. Sum σ α) (a : α) (b : σ) :
    let F : α → ℕ →. Sum σ α := fun a n =>
      n.rec (some (Sum.inr a)) fun _ IH => IH.bind fun s => Sum.casesOn s (fun _ => Part.some s) f
    (∃ n : ℕ,
        ((∃ b' : σ, Sum.inl b' ∈ F a n) ∧ ∀ {m : ℕ}, m < n → ∃ b : α, Sum.inr b ∈ F a m) ∧
          Sum.inl b ∈ F a n) ↔
      b ∈ PFun.fix f a := by
  intro F; refine' ⟨fun h => _, fun h => _⟩
  · rcases h with ⟨n, ⟨_x, h₁⟩, h₂⟩
    have : ∀ m a', Sum.inr a' ∈ F a m → b ∈ PFun.fix f a' → b ∈ PFun.fix f a := by
      

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
σ✝ : Type u_4
inst✝³ : Primcodable α✝
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ✝
α : Type u_5
σ : Type u_6
f : α →. σ ⊕ α
a : α
b : σ
F : α → ℕ →. σ ⊕ α :=
  fun a n =>
    Nat.rec (Part.some (Sum.inr a)) (fun x IH => Part.bind IH fun s => Sum.casesOn s (fun x => Part.some s) f) n
n : ℕ
h₂ : Sum.inl b ∈ F a n
_x : ∃ b', Sum.inl b' ∈ F a n
h₁ : ∀ {m : ℕ}, m < n → ∃ b, Sum.inr b ∈ F a m
⊢ ∀ (m : ℕ) (a' : α), Sum.inr a' ∈ F a m → b ∈ PFun.fix f a' → b ∈ PFun.fix f a

Next tactic:
intro m a' am ba