l3lab/ntp-mathlib huggingface dataset:
theorem mul : Nat.Primrec (unpaired (· * ·)) :=
  (prec zero (add.comp (pair left (right.comp right)))).of_eq fun p => by
    simp; 

Proof state:
p : ℕ
⊢ Nat.rec 0 (fun y IH => (unpair p).1 + IH) (unpair p).2 = (unpair p).1 * (unpair p).2

Next tactic:
induction p.unpair.2
theorem mul : Nat.Primrec (unpaired (· * ·)) :=
  (prec zero (add.comp (pair left (right.comp right)))).of_eq fun p => by
    simp; induction p.unpair.2 <;> 

Proof state:
case zero
p : ℕ
⊢ Nat.rec 0 (fun y IH => (unpair p).1 + IH) Nat.zero = (unpair p).1 * Nat.zero

Next tactic:
simp [*, mul_succ, add_comm _ (unpair p).fst]
theorem mul : Nat.Primrec (unpaired (· * ·)) :=
  (prec zero (add.comp (pair left (right.comp right)))).of_eq fun p => by
    simp; induction p.unpair.2 <;> 

Proof state:
case succ
p n✝ : ℕ
n_ih✝ : Nat.rec 0 (fun y IH => (unpair p).1 + IH) n✝ = (unpair p).1 * n✝
⊢ Nat.rec 0 (fun y IH => (unpair p).1 + IH) (succ n✝) = (unpair p).1 * succ n✝

Next tactic:
simp [*, mul_succ, add_comm _ (unpair p).fst]
theorem pow : Nat.Primrec (unpaired (· ^ ·)) :=
  (prec (const 1) (mul.comp (pair (right.comp right) left))).of_eq fun p => by
    

Proof state:
p : ℕ
⊢ unpaired
      (fun z n =>
        Nat.rec 1
          (fun y IH =>
            unpaired (fun x x_1 => x * x_1)
              (Nat.pair (unpair (unpair (Nat.pair z (Nat.pair y IH))).2).2 (unpair (Nat.pair z (Nat.pair y IH))).1))
          n)
      p =
    unpaired (fun x x_1 => x ^ x_1) p

Next tactic:
simp
theorem pow : Nat.Primrec (unpaired (· ^ ·)) :=
  (prec (const 1) (mul.comp (pair (right.comp right) left))).of_eq fun p => by
    simp; 

Proof state:
p : ℕ
⊢ Nat.rec 1 (fun y IH => IH * (unpair p).1) (unpair p).2 = (unpair p).1 ^ (unpair p).2

Next tactic:
induction p.unpair.2
theorem pow : Nat.Primrec (unpaired (· ^ ·)) :=
  (prec (const 1) (mul.comp (pair (right.comp right) left))).of_eq fun p => by
    simp; induction p.unpair.2 <;> 

Proof state:
case zero
p : ℕ
⊢ Nat.rec 1 (fun y IH => IH * (unpair p).1) Nat.zero = (unpair p).1 ^ Nat.zero

Next tactic:
simp [*, pow_succ]
theorem pow : Nat.Primrec (unpaired (· ^ ·)) :=
  (prec (const 1) (mul.comp (pair (right.comp right) left))).of_eq fun p => by
    simp; induction p.unpair.2 <;> 

Proof state:
case succ
p n✝ : ℕ
n_ih✝ : Nat.rec 1 (fun y IH => IH * (unpair p).1) n✝ = (unpair p).1 ^ n✝
⊢ Nat.rec 1 (fun y IH => IH * (unpair p).1) (succ n✝) = (unpair p).1 ^ succ n✝

Next tactic:
simp [*, pow_succ]
instance (priority := 10) ofDenumerable (α) [Denumerable α] : Primcodable α :=
  ⟨Nat.Primrec.succ.of_eq <| by 

Proof state:
α : Type ?u.12192
inst✝ : Denumerable α
⊢ ∀ (n : ℕ), Nat.succ n = encode (decode n)

Next tactic:
simp
/-- Builds a `Primcodable` instance from an equivalence to a `Primcodable` type. -/
def ofEquiv (α) {β} [Primcodable α] (e : β ≃ α) : Primcodable β :=
  { Encodable.ofEquiv α e with
    prim := (@Primcodable.prim α _).of_eq fun n => by
      

Proof state:
α : Type ?u.13236
β : Type ?u.13243
inst✝ : Primcodable α
e : β ≃ α
src✝ : Encodable β := Encodable.ofEquiv α e
n : ℕ
⊢ encode (decode n) = encode (decode n)

Next tactic:
rw [decode_ofEquiv]
/-- Builds a `Primcodable` instance from an equivalence to a `Primcodable` type. -/
def ofEquiv (α) {β} [Primcodable α] (e : β ≃ α) : Primcodable β :=
  { Encodable.ofEquiv α e with
    prim := (@Primcodable.prim α _).of_eq fun n => by
      rw [decode_ofEquiv]
      

Proof state:
α : Type ?u.13236
β : Type ?u.13243
inst✝ : Primcodable α
e : β ≃ α
src✝ : Encodable β := Encodable.ofEquiv α e
n : ℕ
⊢ encode (decode n) = encode (Option.map (⇑e.symm) (decode n))

Next tactic:
cases (@decode α _ n)
/-- Builds a `Primcodable` instance from an equivalence to a `Primcodable` type. -/
def ofEquiv (α) {β} [Primcodable α] (e : β ≃ α) : Primcodable β :=
  { Encodable.ofEquiv α e with
    prim := (@Primcodable.prim α _).of_eq fun n => by
      rw [decode_ofEquiv]
      cases (@decode α _ n) <;>
        

Proof state:
case none
α : Type ?u.13236
β : Type ?u.13243
inst✝ : Primcodable α
e : β ≃ α
src✝ : Encodable β := Encodable.ofEquiv α e
n : ℕ
⊢ encode none = encode (Option.map (⇑e.symm) none)

Next tactic:
simp [encode_ofEquiv]
/-- Builds a `Primcodable` instance from an equivalence to a `Primcodable` type. -/
def ofEquiv (α) {β} [Primcodable α] (e : β ≃ α) : Primcodable β :=
  { Encodable.ofEquiv α e with
    prim := (@Primcodable.prim α _).of_eq fun n => by
      rw [decode_ofEquiv]
      cases (@decode α _ n) <;>
        

Proof state:
case some
α : Type ?u.13236
β : Type ?u.13243
inst✝ : Primcodable α
e : β ≃ α
src✝ : Encodable β := Encodable.ofEquiv α e
n : ℕ
val✝ : α
⊢ encode (some val✝) = encode (Option.map (⇑e.symm) (some val✝))

Next tactic:
simp [encode_ofEquiv]
instance unit : Primcodable PUnit :=
  ⟨(casesOn1 1 zero).of_eq fun n => by 

Proof state:
n : ℕ
⊢ (Nat.casesOn n 1 fun x => 0) = encode (decode n)

Next tactic:
cases n
instance unit : Primcodable PUnit :=
  ⟨(casesOn1 1 zero).of_eq fun n => by cases n <;> 

Proof state:
case zero
⊢ (Nat.casesOn Nat.zero 1 fun x => 0) = encode (decode Nat.zero)

Next tactic:
simp
instance unit : Primcodable PUnit :=
  ⟨(casesOn1 1 zero).of_eq fun n => by cases n <;> 

Proof state:
case succ
n✝ : ℕ
⊢ (Nat.casesOn (Nat.succ n✝) 1 fun x => 0) = encode (decode (Nat.succ n✝))

Next tactic:
simp
instance option {α : Type*} [h : Primcodable α] : Primcodable (Option α) :=
  ⟨(casesOn1 1 ((casesOn1 0 (.comp .succ .succ)).comp (@Primcodable.prim α _))).of_eq fun n => by
    

Proof state:
α : Type u_1
h : Primcodable α
n : ℕ
⊢ (Nat.casesOn n 1 fun n => Nat.casesOn (encode (decode n)) 0 fun n => Nat.succ (Nat.succ n)) = encode (decode n)

Next tactic:
cases n with
      | zero => rfl
      | succ n =>
        rw [decode_option_succ]
        cases H : @decode α _ n <;> simp [H]
instance option {α : Type*} [h : Primcodable α] : Primcodable (Option α) :=
  ⟨(casesOn1 1 ((casesOn1 0 (.comp .succ .succ)).comp (@Primcodable.prim α _))).of_eq fun n => by
    cases n with
      

Proof state:
case zero
α : Type u_1
h : Primcodable α
⊢ (Nat.casesOn Nat.zero 1 fun n => Nat.casesOn (encode (decode n)) 0 fun n => Nat.succ (Nat.succ n)) =
    encode (decode Nat.zero)

Next tactic:
| zero => rfl
instance option {α : Type*} [h : Primcodable α] : Primcodable (Option α) :=
  ⟨(casesOn1 1 ((casesOn1 0 (.comp .succ .succ)).comp (@Primcodable.prim α _))).of_eq fun n => by
    cases n with
      | zero => 

Proof state:
case zero
α : Type u_1
h : Primcodable α
⊢ (Nat.casesOn Nat.zero 1 fun n => Nat.casesOn (encode (decode n)) 0 fun n => Nat.succ (Nat.succ n)) =
    encode (decode Nat.zero)

Next tactic:
rfl
instance option {α : Type*} [h : Primcodable α] : Primcodable (Option α) :=
  ⟨(casesOn1 1 ((casesOn1 0 (.comp .succ .succ)).comp (@Primcodable.prim α _))).of_eq fun n => by
    cases n with
      | zero => rfl
      

Proof state:
case succ
α : Type u_1
h : Primcodable α
n : ℕ
⊢ (Nat.casesOn (Nat.succ n) 1 fun n => Nat.casesOn (encode (decode n)) 0 fun n => Nat.succ (Nat.succ n)) =
    encode (decode (Nat.succ n))

Next tactic:
| succ n =>
        rw [decode_option_succ]
        cases H : @decode α _ n <;> simp [H]
instance option {α : Type*} [h : Primcodable α] : Primcodable (Option α) :=
  ⟨(casesOn1 1 ((casesOn1 0 (.comp .succ .succ)).comp (@Primcodable.prim α _))).of_eq fun n => by
    cases n with
      | zero => rfl
      | succ n =>
        

Proof state:
case succ
α : Type u_1
h : Primcodable α
n : ℕ
⊢ (Nat.casesOn (Nat.succ n) 1 fun n => Nat.casesOn (encode (decode n)) 0 fun n => Nat.succ (Nat.succ n)) =
    encode (decode (Nat.succ n))

Next tactic:
rw [decode_option_succ]
instance option {α : Type*} [h : Primcodable α] : Primcodable (Option α) :=
  ⟨(casesOn1 1 ((casesOn1 0 (.comp .succ .succ)).comp (@Primcodable.prim α _))).of_eq fun n => by
    cases n with
      | zero => rfl
      | succ n =>
        rw [decode_option_succ]
        

Proof state:
case succ
α : Type u_1
h : Primcodable α
n : ℕ
⊢ (Nat.casesOn (Nat.succ n) 1 fun n => Nat.casesOn (encode (decode n)) 0 fun n => Nat.succ (Nat.succ n)) =
    encode (Option.map some (decode n))

Next tactic:
cases H : @decode α _ n
instance option {α : Type*} [h : Primcodable α] : Primcodable (Option α) :=
  ⟨(casesOn1 1 ((casesOn1 0 (.comp .succ .succ)).comp (@Primcodable.prim α _))).of_eq fun n => by
    cases n with
      | zero => rfl
      | succ n =>
        rw [decode_option_succ]
        cases H : @decode α _ n <;> 

Proof state:
case succ.none
α : Type u_1
h : Primcodable α
n : ℕ
H : decode n = none
⊢ (Nat.casesOn (Nat.succ n) 1 fun n => Nat.casesOn (encode (decode n)) 0 fun n => Nat.succ (Nat.succ n)) =
    encode (Option.map some none)

Next tactic:
simp [H]
instance option {α : Type*} [h : Primcodable α] : Primcodable (Option α) :=
  ⟨(casesOn1 1 ((casesOn1 0 (.comp .succ .succ)).comp (@Primcodable.prim α _))).of_eq fun n => by
    cases n with
      | zero => rfl
      | succ n =>
        rw [decode_option_succ]
        cases H : @decode α _ n <;> 

Proof state:
case succ.some
α : Type u_1
h : Primcodable α
n : ℕ
val✝ : α
H : decode n = some val✝
⊢ (Nat.casesOn (Nat.succ n) 1 fun n => Nat.casesOn (encode (decode n)) 0 fun n => Nat.succ (Nat.succ n)) =
    encode (Option.map some (some val✝))

Next tactic:
simp [H]
instance bool : Primcodable Bool :=
  ⟨(casesOn1 1 (casesOn1 2 zero)).of_eq fun n => match n with
    | 0 => rfl
    | 1 => rfl
    | (n + 2) => by 

Proof state:
n✝ n : ℕ
⊢ (Nat.casesOn (n + 2) 1 fun x => Nat.casesOn x 2 fun x => 0) = encode (decode (n + 2))

Next tactic:
rw [decode_ge_two]
instance bool : Primcodable Bool :=
  ⟨(casesOn1 1 (casesOn1 2 zero)).of_eq fun n => match n with
    | 0 => rfl
    | 1 => rfl
    | (n + 2) => by rw [decode_ge_two] <;> 

Proof state:
n✝ n : ℕ
⊢ (Nat.casesOn (n + 2) 1 fun x => Nat.casesOn x 2 fun x => 0) = encode none

Next tactic:
simp
instance bool : Primcodable Bool :=
  ⟨(casesOn1 1 (casesOn1 2 zero)).of_eq fun n => match n with
    | 0 => rfl
    | 1 => rfl
    | (n + 2) => by rw [decode_ge_two] <;> 

Proof state:
case h
n✝ n : ℕ
⊢ 2 ≤ n + 2

Next tactic:
simp
protected theorem encode : Primrec (@encode α _) :=
  (@Primcodable.prim α _).of_eq fun n => by 

Proof state:
α : Type u_1
β : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
n : ℕ
⊢ encode (decode n) = encode (Option.map encode (decode n))

Next tactic:
cases @decode α _ n
protected theorem encode : Primrec (@encode α _) :=
  (@Primcodable.prim α _).of_eq fun n => by cases @decode α _ n <;> 

Proof state:
case none
α : Type u_1
β : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
n : ℕ
⊢ encode none = encode (Option.map encode none)

Next tactic:
rfl
protected theorem encode : Primrec (@encode α _) :=
  (@Primcodable.prim α _).of_eq fun n => by cases @decode α _ n <;> 

Proof state:
case some
α : Type u_1
β : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
n : ℕ
val✝ : α
⊢ encode (some val✝) = encode (Option.map encode (some val✝))

Next tactic:
rfl
theorem dom_denumerable {α β} [Denumerable α] [Primcodable β] {f : α → β} :
    Primrec f ↔ Nat.Primrec fun n => encode (f (ofNat α n)) :=
  ⟨fun h => (pred.comp h).of_eq fun n => by 

Proof state:
α✝ : Type u_1
β✝ : Type u_2
σ : Type u_3
inst✝⁴ : Primcodable α✝
inst✝³ : Primcodable β✝
inst✝² : Primcodable σ
α : Type u_4
β : Type u_5
inst✝¹ : Denumerable α
inst✝ : Primcodable β
f : α → β
h : Primrec f
n : ℕ
⊢ Nat.pred (encode (Option.map f (decode n))) = encode (f (ofNat α n))

Next tactic:
simp
theorem dom_denumerable {α β} [Denumerable α] [Primcodable β] {f : α → β} :
    Primrec f ↔ Nat.Primrec fun n => encode (f (ofNat α n)) :=
  ⟨fun h => (pred.comp h).of_eq fun n => by simp, fun h =>
    (Nat.Primrec.succ.comp h).of_eq fun n => by 

Proof state:
α✝ : Type u_1
β✝ : Type u_2
σ : Type u_3
inst✝⁴ : Primcodable α✝
inst✝³ : Primcodable β✝
inst✝² : Primcodable σ
α : Type u_4
β : Type u_5
inst✝¹ : Denumerable α
inst✝ : Primcodable β
f : α → β
h : Nat.Primrec fun n => encode (f (ofNat α n))
n : ℕ
⊢ Nat.succ (encode (f (ofNat α n))) = encode (Option.map f (decode n))

Next tactic:
simp
theorem option_some : Primrec (@some α) :=
  ((casesOn1 0 (Nat.Primrec.succ.comp .succ)).comp (@Primcodable.prim α _)).of_eq fun n => by
    

Proof state:
α : Type u_1
β : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
n : ℕ
⊢ (Nat.casesOn (encode (decode n)) 0 fun n => Nat.succ (Nat.succ n)) = encode (Option.map some (decode n))

Next tactic:
cases @decode α _ n
theorem option_some : Primrec (@some α) :=
  ((casesOn1 0 (Nat.Primrec.succ.comp .succ)).comp (@Primcodable.prim α _)).of_eq fun n => by
    cases @decode α _ n <;> 

Proof state:
case none
α : Type u_1
β : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
n : ℕ
⊢ (Nat.casesOn (encode none) 0 fun n => Nat.succ (Nat.succ n)) = encode (Option.map some none)

Next tactic:
simp
theorem option_some : Primrec (@some α) :=
  ((casesOn1 0 (Nat.Primrec.succ.comp .succ)).comp (@Primcodable.prim α _)).of_eq fun n => by
    cases @decode α _ n <;> 

Proof state:
case some
α : Type u_1
β : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
n : ℕ
val✝ : α
⊢ (Nat.casesOn (encode (some val✝)) 0 fun n => Nat.succ (Nat.succ n)) = encode (Option.map some (some val✝))

Next tactic:
simp
theorem const (x : σ) : Primrec fun _ : α => x :=
  ((casesOn1 0 (.const (encode x).succ)).comp (@Primcodable.prim α _)).of_eq fun n => by
    

Proof state:
α : Type u_1
β : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
x : σ
n : ℕ
⊢ (Nat.casesOn (encode (decode n)) 0 fun x_1 => Nat.succ (encode x)) = encode (Option.map (fun x_1 => x) (decode n))

Next tactic:
cases @decode α _ n
theorem const (x : σ) : Primrec fun _ : α => x :=
  ((casesOn1 0 (.const (encode x).succ)).comp (@Primcodable.prim α _)).of_eq fun n => by
    cases @decode α _ n <;> 

Proof state:
case none
α : Type u_1
β : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
x : σ
n : ℕ
⊢ (Nat.casesOn (encode none) 0 fun x_1 => Nat.succ (encode x)) = encode (Option.map (fun x_1 => x) none)

Next tactic:
rfl
theorem const (x : σ) : Primrec fun _ : α => x :=
  ((casesOn1 0 (.const (encode x).succ)).comp (@Primcodable.prim α _)).of_eq fun n => by
    cases @decode α _ n <;> 

Proof state:
case some
α : Type u_1
β : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
x : σ
n : ℕ
val✝ : α
⊢ (Nat.casesOn (encode (some val✝)) 0 fun x_1 => Nat.succ (encode x)) = encode (Option.map (fun x_1 => x) (some val✝))

Next tactic:
rfl
protected theorem id : Primrec (@id α) :=
  (@Primcodable.prim α).of_eq <| by 

Proof state:
α : Type u_1
β : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
⊢ ∀ (n : ℕ), encode (decode n) = encode (Option.map id (decode n))

Next tactic:
simp
theorem comp {f : β → σ} {g : α → β} (hf : Primrec f) (hg : Primrec g) : Primrec fun a => f (g a) :=
  ((casesOn1 0 (.comp hf (pred.comp hg))).comp (@Primcodable.prim α _)).of_eq fun n => by
    

Proof state:
α : Type u_1
β : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
f : β → σ
g : α → β
hf : Primrec f
hg : Primrec g
n : ℕ
⊢ (Nat.casesOn (encode (decode n)) 0 fun n =>
      encode (Option.map f (decode (Nat.pred (encode (Option.map g (decode n))))))) =
    encode (Option.map (fun a => f (g a)) (decode n))

Next tactic:
cases @decode α _ n
theorem comp {f : β → σ} {g : α → β} (hf : Primrec f) (hg : Primrec g) : Primrec fun a => f (g a) :=
  ((casesOn1 0 (.comp hf (pred.comp hg))).comp (@Primcodable.prim α _)).of_eq fun n => by
    cases @decode α _ n <;> 

Proof state:
case none
α : Type u_1
β : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
f : β → σ
g : α → β
hf : Primrec f
hg : Primrec g
n : ℕ
⊢ (Nat.casesOn (encode none) 0 fun n => encode (Option.map f (decode (Nat.pred (encode (Option.map g (decode n))))))) =
    encode (Option.map (fun a => f (g a)) none)

Next tactic:
simp [encodek]
theorem comp {f : β → σ} {g : α → β} (hf : Primrec f) (hg : Primrec g) : Primrec fun a => f (g a) :=
  ((casesOn1 0 (.comp hf (pred.comp hg))).comp (@Primcodable.prim α _)).of_eq fun n => by
    cases @decode α _ n <;> 

Proof state:
case some
α : Type u_1
β : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
f : β → σ
g : α → β
hf : Primrec f
hg : Primrec g
n : ℕ
val✝ : α
⊢ (Nat.casesOn (encode (some val✝)) 0 fun n =>
      encode (Option.map f (decode (Nat.pred (encode (Option.map g (decode n))))))) =
    encode (Option.map (fun a => f (g a)) (some val✝))

Next tactic:
simp [encodek]
theorem encode_iff {f : α → σ} : (Primrec fun a => encode (f a)) ↔ Primrec f :=
  ⟨fun h => Nat.Primrec.of_eq h fun n => by 

Proof state:
α : Type u_1
β : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
f : α → σ
h : Primrec fun a => encode (f a)
n : ℕ
⊢ encode (Option.map (fun a => encode (f a)) (decode n)) = encode (Option.map f (decode n))

Next tactic:
cases @decode α _ n
theorem encode_iff {f : α → σ} : (Primrec fun a => encode (f a)) ↔ Primrec f :=
  ⟨fun h => Nat.Primrec.of_eq h fun n => by cases @decode α _ n <;> 

Proof state:
case none
α : Type u_1
β : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
f : α → σ
h : Primrec fun a => encode (f a)
n : ℕ
⊢ encode (Option.map (fun a => encode (f a)) none) = encode (Option.map f none)

Next tactic:
rfl
theorem encode_iff {f : α → σ} : (Primrec fun a => encode (f a)) ↔ Primrec f :=
  ⟨fun h => Nat.Primrec.of_eq h fun n => by cases @decode α _ n <;> 

Proof state:
case some
α : Type u_1
β : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
f : α → σ
h : Primrec fun a => encode (f a)
n : ℕ
val✝ : α
⊢ encode (Option.map (fun a => encode (f a)) (some val✝)) = encode (Option.map f (some val✝))

Next tactic:
rfl
theorem of_equiv_symm {β} {e : β ≃ α} :
    haveI := Primcodable.ofEquiv α e
    Primrec e.symm :=
  letI := Primcodable.ofEquiv α e
  encode_iff.1 (show Primrec fun a => encode (e (e.symm a)) by 

Proof state:
α : Type u_1
β✝ : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β✝
inst✝ : Primcodable σ
β : Type u_4
e : β ≃ α
this : Primcodable β := Primcodable.ofEquiv α e
⊢ Primrec fun a => encode (e (e.symm a))

Next tactic:
simp [Primrec.encode]
theorem of_equiv_iff {β} (e : β ≃ α) {f : σ → β} :
    haveI := Primcodable.ofEquiv α e
    (Primrec fun a => e (f a)) ↔ Primrec f :=
  letI := Primcodable.ofEquiv α e
  ⟨fun h => (of_equiv_symm.comp h).of_eq fun a => by 

Proof state:
α : Type u_1
β✝ : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β✝
inst✝ : Primcodable σ
β : Type u_4
e : β ≃ α
f : σ → β
this : Primcodable β := Primcodable.ofEquiv α e
h : Primrec fun a => e (f a)
a : σ
⊢ e.symm (e (f a)) = f a

Next tactic:
simp
theorem of_equiv_symm_iff {β} (e : β ≃ α) {f : σ → α} :
    haveI := Primcodable.ofEquiv α e
    (Primrec fun a => e.symm (f a)) ↔ Primrec f :=
  letI := Primcodable.ofEquiv α e
  ⟨fun h => (of_equiv.comp h).of_eq fun a => by 

Proof state:
α : Type u_1
β✝ : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β✝
inst✝ : Primcodable σ
β : Type u_4
e : β ≃ α
f : σ → α
this : Primcodable β := Primcodable.ofEquiv α e
h : Primrec fun a => e.symm (f a)
a : σ
⊢ e (e.symm (f a)) = f a

Next tactic:
simp
instance prod {α β} [Primcodable α] [Primcodable β] : Primcodable (α × β) :=
  ⟨((casesOn' zero ((casesOn' zero .succ).comp (pair right ((@Primcodable.prim β).comp left)))).comp
          (pair right ((@Primcodable.prim α).comp left))).of_eq
      fun n => by
      

Proof state:
α : Type ?u.29162
β : Type ?u.29165
inst✝¹ : Primcodable α
inst✝ : Primcodable β
n : ℕ
⊢ Nat.unpaired
      (fun z n =>
        Nat.casesOn n 0 fun y =>
          Nat.unpaired (fun z n => Nat.casesOn n 0 fun y => Nat.succ (Nat.pair z y))
            (Nat.pair (Nat.unpair (Nat.pair z y)).2 (encode (decode (Nat.unpair (Nat.pair z y)).1))))
      (Nat.pair (Nat.unpair n).2 (encode (decode (Nat.unpair n).1))) =
    encode (decode n)

Next tactic:
simp only [Nat.unpaired, Nat.unpair_pair, decode_prod_val]
instance prod {α β} [Primcodable α] [Primcodable β] : Primcodable (α × β) :=
  ⟨((casesOn' zero ((casesOn' zero .succ).comp (pair right ((@Primcodable.prim β).comp left)))).comp
          (pair right ((@Primcodable.prim α).comp left))).of_eq
      fun n => by
      simp only [Nat.unpaired, Nat.unpair_pair, decode_prod_val]
      

Proof state:
α : Type ?u.29162
β : Type ?u.29165
inst✝¹ : Primcodable α
inst✝ : Primcodable β
n : ℕ
⊢ Nat.rec 0 (fun n_1 n_ih => Nat.rec 0 (fun n n_ih => Nat.succ (Nat.pair n_1 n)) (encode (decode (Nat.unpair n).2)))
      (encode (decode (Nat.unpair n).1)) =
    encode (Option.bind (decode (Nat.unpair n).1) fun a => Option.map (Prod.mk a) (decode (Nat.unpair n).2))

Next tactic:
cases @decode α _ n.unpair.1
instance prod {α β} [Primcodable α] [Primcodable β] : Primcodable (α × β) :=
  ⟨((casesOn' zero ((casesOn' zero .succ).comp (pair right ((@Primcodable.prim β).comp left)))).comp
          (pair right ((@Primcodable.prim α).comp left))).of_eq
      fun n => by
      simp only [Nat.unpaired, Nat.unpair_pair, decode_prod_val]
      cases @decode α _ n.unpair.1; · 

Proof state:
case none
α : Type ?u.29162
β : Type ?u.29165
inst✝¹ : Primcodable α
inst✝ : Primcodable β
n : ℕ
⊢ Nat.rec 0 (fun n_1 n_ih => Nat.rec 0 (fun n n_ih => Nat.succ (Nat.pair n_1 n)) (encode (decode (Nat.unpair n).2)))
      (encode none) =
    encode (Option.bind none fun a => Option.map (Prod.mk a) (decode (Nat.unpair n).2))

Next tactic:
simp
instance prod {α β} [Primcodable α] [Primcodable β] : Primcodable (α × β) :=
  ⟨((casesOn' zero ((casesOn' zero .succ).comp (pair right ((@Primcodable.prim β).comp left)))).comp
          (pair right ((@Primcodable.prim α).comp left))).of_eq
      fun n => by
      simp only [Nat.unpaired, Nat.unpair_pair, decode_prod_val]
      cases @decode α _ n.unpair.1; · simp
      

Proof state:
case some
α : Type ?u.29162
β : Type ?u.29165
inst✝¹ : Primcodable α
inst✝ : Primcodable β
n : ℕ
val✝ : α
⊢ Nat.rec 0 (fun n_1 n_ih => Nat.rec 0 (fun n n_ih => Nat.succ (Nat.pair n_1 n)) (encode (decode (Nat.unpair n).2)))
      (encode (some val✝)) =
    encode (Option.bind (some val✝) fun a => Option.map (Prod.mk a) (decode (Nat.unpair n).2))

Next tactic:
cases @decode β _ n.unpair.2
instance prod {α β} [Primcodable α] [Primcodable β] : Primcodable (α × β) :=
  ⟨((casesOn' zero ((casesOn' zero .succ).comp (pair right ((@Primcodable.prim β).comp left)))).comp
          (pair right ((@Primcodable.prim α).comp left))).of_eq
      fun n => by
      simp only [Nat.unpaired, Nat.unpair_pair, decode_prod_val]
      cases @decode α _ n.unpair.1; · simp
      cases @decode β _ n.unpair.2 <;> 

Proof state:
case some.none
α : Type ?u.29162
β : Type ?u.29165
inst✝¹ : Primcodable α
inst✝ : Primcodable β
n : ℕ
val✝ : α
⊢ Nat.rec 0 (fun n n_ih => Nat.rec 0 (fun n_1 n_ih => Nat.succ (Nat.pair n n_1)) (encode none)) (encode (some val✝)) =
    encode (Option.bind (some val✝) fun a => Option.map (Prod.mk a) none)

Next tactic:
simp
instance prod {α β} [Primcodable α] [Primcodable β] : Primcodable (α × β) :=
  ⟨((casesOn' zero ((casesOn' zero .succ).comp (pair right ((@Primcodable.prim β).comp left)))).comp
          (pair right ((@Primcodable.prim α).comp left))).of_eq
      fun n => by
      simp only [Nat.unpaired, Nat.unpair_pair, decode_prod_val]
      cases @decode α _ n.unpair.1; · simp
      cases @decode β _ n.unpair.2 <;> 

Proof state:
case some.some
α : Type ?u.29162
β : Type ?u.29165
inst✝¹ : Primcodable α
inst✝ : Primcodable β
n : ℕ
val✝¹ : α
val✝ : β
⊢ Nat.rec 0 (fun n n_ih => Nat.rec 0 (fun n_1 n_ih => Nat.succ (Nat.pair n n_1)) (encode (some val✝)))
      (encode (some val✝¹)) =
    encode (Option.bind (some val✝¹) fun a => Option.map (Prod.mk a) (some val✝))

Next tactic:
simp