Theorem: Primrec.nat_rec
File: Mathlib/Computability/Primrec.lean

Proof steps:
state_before: α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
σ : Type u_5
inst✝⁴ : Primcodable α
inst✝³ : Primcodable β
inst✝² : Primcodable γ
inst✝¹ : Primcodable δ
inst✝ : Primcodable σ
f : α → β
g : α → ℕ × β → β
hf : Primrec f
hg : Primrec₂ g
n : ℕ
⊢ Nat.unpaired
      (fun z n =>
        Nat.casesOn n 0 fun y =>
          Nat.unpaired
            (fun z n =>
              Nat.rec (encode (Option.map f (decode z)))
                (fun y IH =>
                  encode
                    (Option.map (fun p => g p.1 p.2)
                      (decode
                        (Nat.pair (Nat.unpair (Nat.pair z (Nat.pair y IH))).1
                          (Nat.pair (Nat.unpair (Nat.unpair (Nat.pair z (Nat.pair y IH))).2).1
                            (Nat.unpair (Nat.unpair (Nat.pair z (Nat.pair y IH))).2).2.pred)))))
                n)
            (Nat.pair (Nat.unpair (Nat.pair z y)).2 (Nat.unpair (Nat.unpair (Nat.pair z y)).1).2))
      (Nat.pair (id n) (encode (decode (Nat.unpair n).1))) =
    Nat.unpaired
      (fun m n =>
        encode ((decode m).bind fun a => Option.map (fun n => Nat.rec (f a) (fun n IH => g a (n, IH)) n) (decode n)))
      n
state_after: α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
σ : Type u_5
inst✝⁴ : Primcodable α
inst✝³ : Primcodable β
inst✝² : Primcodable γ
inst✝¹ : Primcodable δ
inst✝ : Primcodable σ
f : α → β
g : α → ℕ × β → β
hf : Primrec f
hg : Primrec₂ g
n : ℕ
⊢ Nat.rec 0
      (fun n_1 n_ih =>
        Nat.rec (encode (Option.map f (decode n_1)))
          (fun y IH =>
            encode
              (Option.map (fun p => g p.1 p.2)
                ((decode n_1).bind fun a => Option.map (Prod.mk a ∘ Prod.mk y) (decode IH.pred))))
          (Nat.unpair n).2)
      (encode (decode (Nat.unpair n).1)) =
    encode ((decode (Nat.unpair n).1).bind fun a => some (Nat.rec (f a) (fun n IH => g a (n, IH)) (Nat.unpair n).2))
tactic: simp only [Nat.unpaired, id_eq, Nat.unpair_pair, decode_prod_val, decode_nat,
        Option.some_bind, Option.map_map, Option.map_some']
state_before: α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
σ : Type u_5
inst✝⁴ : Primcodable α
inst✝³ : Primcodable β
inst✝² : Primcodable γ
inst✝¹ : Primcodable δ
inst✝ : Primcodable σ
f : α → β
g : α → ℕ × β → β
hf : Primrec f
hg : Primrec₂ g
n : ℕ
⊢ Nat.rec 0
      (fun n_1 n_ih =>
        Nat.rec (encode (Option.map f (decode n_1)))
          (fun y IH =>
            encode
              (Option.map (fun p => g p.1 p.2)
                ((decode n_1).bind fun a => Option.map (Prod.mk a ∘ Prod.mk y) (decode IH.pred))))
          (Nat.unpair n).2)
      (encode (decode (Nat.unpair n).1)) =
    encode ((decode (Nat.unpair n).1).bind fun a => some (Nat.rec (f a) (fun n IH => g a (n, IH)) (Nat.unpair n).2))
state_after: case none
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
σ : Type u_5
inst✝⁴ : Primcodable α
inst✝³ : Primcodable β
inst✝² : Primcodable γ
inst✝¹ : Primcodable δ
inst✝ : Primcodable σ
f : α → β
g : α → ℕ × β → β
hf : Primrec f
hg : Primrec₂ g
n : ℕ
⊢ Nat.rec 0
      (fun n_1 n_ih =>
        Nat.rec (encode (Option.map f (decode n_1)))
          (fun y IH =>
            encode
              (Option.map (fun p => g p.1 p.2)
                ((decode n_1).bind fun a => Option.map (Prod.mk a ∘ Prod.mk y) (decode IH.pred))))
          (Nat.unpair n).2)
      (encode none) =
    encode (none.bind fun a => some (Nat.rec (f a) (fun n IH => g a (n, IH)) (Nat.unpair n).2))

case some
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
σ : Type u_5
inst✝⁴ : Primcodable α
inst✝³ : Primcodable β
inst✝² : Primcodable γ
inst✝¹ : Primcodable δ
inst✝ : Primcodable σ
f : α → β
g : α → ℕ × β → β
hf : Primrec f
hg : Primrec₂ g
n : ℕ
a : α
⊢ Nat.rec 0
      (fun n_1 n_ih =>
        Nat.rec (encode (Option.map f (decode n_1)))
          (fun y IH =>
            encode
              (Option.map (fun p => g p.1 p.2)
                ((decode n_1).bind fun a => Option.map (Prod.mk a ∘ Prod.mk y) (decode IH.pred))))
          (Nat.unpair n).2)
      (encode (some a)) =
    encode ((some a).bind fun a => some (Nat.rec (f a) (fun n IH => g a (n, IH)) (Nat.unpair n).2))
tactic: cases' @decode α _ n.unpair.1 with a
state_before: case some
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
σ : Type u_5
inst✝⁴ : Primcodable α
inst✝³ : Primcodable β
inst✝² : Primcodable γ
inst✝¹ : Primcodable δ
inst✝ : Primcodable σ
f : α → β
g : α → ℕ × β → β
hf : Primrec f
hg : Primrec₂ g
n : ℕ
a : α
⊢ Nat.rec 0
      (fun n_1 n_ih =>
        Nat.rec (encode (Option.map f (decode n_1)))
          (fun y IH =>
            encode
              (Option.map (fun p => g p.1 p.2)
                ((decode n_1).bind fun a => Option.map (Prod.mk a ∘ Prod.mk y) (decode IH.pred))))
          (Nat.unpair n).2)
      (encode (some a)) =
    encode ((some a).bind fun a => some (Nat.rec (f a) (fun n IH => g a (n, IH)) (Nat.unpair n).2))
state_after: case some
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
σ : Type u_5
inst✝⁴ : Primcodable α
inst✝³ : Primcodable β
inst✝² : Primcodable γ
inst✝¹ : Primcodable δ
inst✝ : Primcodable σ
f : α → β
g : α → ℕ × β → β
hf : Primrec f
hg : Primrec₂ g
n : ℕ
a : α
⊢ Nat.rec (encode (f a) + 1)
      (fun y IH => encode (Option.map ((fun p => g p.1 p.2) ∘ Prod.mk a ∘ Prod.mk y) (decode (IH - 1))))
      (Nat.unpair n).2 =
    encode (Nat.rec (f a) (fun n IH => g a (n, IH)) (Nat.unpair n).2) + 1
tactic: simp only [Nat.pred_eq_sub_one, encode_some, Nat.succ_eq_add_one, encodek, Option.map_some',
        Option.some_bind, Option.map_map]
state_before: case some
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
σ : Type u_5
inst✝⁴ : Primcodable α
inst✝³ : Primcodable β
inst✝² : Primcodable γ
inst✝¹ : Primcodable δ
inst✝ : Primcodable σ
f : α → β
g : α → ℕ × β → β
hf : Primrec f
hg : Primrec₂ g
n : ℕ
a : α
⊢ Nat.rec (encode (f a) + 1)
      (fun y IH => encode (Option.map ((fun p => g p.1 p.2) ∘ Prod.mk a ∘ Prod.mk y) (decode (IH - 1))))
      (Nat.unpair n).2 =
    encode (Nat.rec (f a) (fun n IH => g a (n, IH)) (Nat.unpair n).2) + 1
state_after: case some.succ
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
σ : Type u_5
inst✝⁴ : Primcodable α
inst✝³ : Primcodable β
inst✝² : Primcodable γ
inst✝¹ : Primcodable δ
inst✝ : Primcodable σ
f : α → β
g : α → ℕ × β → β
hf : Primrec f
hg : Primrec₂ g
n : ℕ
a : α
m : ℕ
a✝ :
  Nat.rec (encode (f a) + 1)
      (fun y IH => encode (Option.map ((fun p => g p.1 p.2) ∘ Prod.mk a ∘ Prod.mk y) (decode (IH - 1)))) m =
    encode (Nat.rec (f a) (fun n IH => g a (n, IH)) m) + 1
⊢ encode
      (Option.map ((fun p => g p.1 p.2) ∘ Prod.mk a ∘ Prod.mk m)
        (decode
          (Nat.rec (encode (f a) + 1)
              (fun y IH => encode (Option.map ((fun p => g p.1 p.2) ∘ Prod.mk a ∘ Prod.mk y) (decode (IH - 1)))) m -
            1))) =
    encode (g a (m, Nat.rec (f a) (fun n IH => g a (n, IH)) m)) + 1
tactic: induction' n.unpair.2 with m <;> simp [encodek]
state_before: case some.succ
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
σ : Type u_5
inst✝⁴ : Primcodable α
inst✝³ : Primcodable β
inst✝² : Primcodable γ
inst✝¹ : Primcodable δ
inst✝ : Primcodable σ
f : α → β
g : α → ℕ × β → β
hf : Primrec f
hg : Primrec₂ g
n : ℕ
a : α
m : ℕ
a✝ :
  Nat.rec (encode (f a) + 1)
      (fun y IH => encode (Option.map ((fun p => g p.1 p.2) ∘ Prod.mk a ∘ Prod.mk y) (decode (IH - 1)))) m =
    encode (Nat.rec (f a) (fun n IH => g a (n, IH)) m) + 1
⊢ encode
      (Option.map ((fun p => g p.1 p.2) ∘ Prod.mk a ∘ Prod.mk m)
        (decode
          (Nat.rec (encode (f a) + 1)
              (fun y IH => encode (Option.map ((fun p => g p.1 p.2) ∘ Prod.mk a ∘ Prod.mk y) (decode (IH - 1)))) m -
            1))) =
    encode (g a (m, Nat.rec (f a) (fun n IH => g a (n, IH)) m)) + 1
state_after: no goals
tactic: simp [*, encodek]