l3lab/ntp-mathlib huggingface dataset:
instance list : Primcodable (List α) :=
  ⟨letI H := @Primcodable.prim (List ℕ) _
    have : Primrec₂ fun (a : α) (o : Option (List ℕ)) => o.map (List.cons (encode a)) :=
      option_map snd <| (list_cons' H).comp ((@Primrec.encode α _).comp (fst.comp fst)) snd
    have :
      Primrec fun n =>
        (ofNat (List ℕ) n).reverse.foldl
          (fun o m => (@decode α _ m).bind fun a => o.map (List.cons (encode a))) (some []) :=
      list_foldl' H ((list_reverse' H).comp (.ofNat (List ℕ))) (const (some []))
        (Primrec.comp₂ (bind_decode_iff.2 <| .swap this) Primrec₂.right)
    nat_iff.1 <|
      (encode_iff.2 this).of_eq fun n => by
        rw [List.foldl_reverse]
        apply Nat.case_strong_induction_on n; · simp
        intro n IH; simp
        cases' @decode α _ n.unpair.1 with a; · rfl
        simp only [decode_eq_ofNat, Option.some.injEq, Option.some_bind, Option.map_some']
        

Proof state:
case hi.some
α : Type u_1
β : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable β
H : Nat.Primrec fun n => encode (decode n) := prim
this✝ : Primrec₂ fun a o => Option.map (List.cons (encode a)) o
this :
  Primrec fun n =>
    List.foldl (fun o m => Option.bind (decode m) fun a => Option.map (List.cons (encode a)) o) (some [])
      (List.reverse (ofNat (List ℕ) n))
n✝ n : ℕ
IH :
  ∀ m ≤ n,
    encode
        (List.foldr (fun x y => Option.bind (decode x) fun a => Option.map (List.cons (encode a)) y) (some [])
          (ofNat (List ℕ) m)) =
      encode (decode m)
a : α
⊢ encode
      (Option.map (List.cons (encode a))
        (List.foldr (fun x y => Option.bind (decode x) fun a => Option.map (List.cons (encode a)) y) (some [])
          (ofNat (List ℕ) (Nat.unpair n).2))) =
    encode (Seq.seq (some fun x => a :: x) fun x => decode (Nat.unpair n).2)

Next tactic:
suffices :
          ∀ (o : Option (List ℕ)) (p) (_ : encode o = encode p),
            encode (Option.map (List.cons (encode a)) o) = encode (Option.map (List.cons a) p)
instance list : Primcodable (List α) :=
  ⟨letI H := @Primcodable.prim (List ℕ) _
    have : Primrec₂ fun (a : α) (o : Option (List ℕ)) => o.map (List.cons (encode a)) :=
      option_map snd <| (list_cons' H).comp ((@Primrec.encode α _).comp (fst.comp fst)) snd
    have :
      Primrec fun n =>
        (ofNat (List ℕ) n).reverse.foldl
          (fun o m => (@decode α _ m).bind fun a => o.map (List.cons (encode a))) (some []) :=
      list_foldl' H ((list_reverse' H).comp (.ofNat (List ℕ))) (const (some []))
        (Primrec.comp₂ (bind_decode_iff.2 <| .swap this) Primrec₂.right)
    nat_iff.1 <|
      (encode_iff.2 this).of_eq fun n => by
        rw [List.foldl_reverse]
        apply Nat.case_strong_induction_on n; · simp
        intro n IH; simp
        cases' @decode α _ n.unpair.1 with a; · rfl
        simp only [decode_eq_ofNat, Option.some.injEq, Option.some_bind, Option.map_some']
        suffices :
          ∀ (o : Option (List ℕ)) (p) (_ : encode o = encode p),
            encode (Option.map (List.cons (encode a)) o) = encode (Option.map (List.cons a) p)
        

Proof state:
case hi.some
α : Type u_1
β : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable β
H : Nat.Primrec fun n => encode (decode n) := prim
this✝¹ : Primrec₂ fun a o => Option.map (List.cons (encode a)) o
this✝ :
  Primrec fun n =>
    List.foldl (fun o m => Option.bind (decode m) fun a => Option.map (List.cons (encode a)) o) (some [])
      (List.reverse (ofNat (List ℕ) n))
n✝ n : ℕ
IH :
  ∀ m ≤ n,
    encode
        (List.foldr (fun x y => Option.bind (decode x) fun a => Option.map (List.cons (encode a)) y) (some [])
          (ofNat (List ℕ) m)) =
      encode (decode m)
a : α
this :
  ∀ (o : Option (List ℕ)) (p : Option (List α)),
    encode o = encode p → encode (Option.map (List.cons (encode a)) o) = encode (Option.map (List.cons a) p)
⊢ encode
      (Option.map (List.cons (encode a))
        (List.foldr (fun x y => Option.bind (decode x) fun a => Option.map (List.cons (encode a)) y) (some [])
          (ofNat (List ℕ) (Nat.unpair n).2))) =
    encode (Seq.seq (some fun x => a :: x) fun x => decode (Nat.unpair n).2)
case this
α : Type u_1
β : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable β
H : Nat.Primrec fun n => encode (decode n) := prim
this✝ : Primrec₂ fun a o => Option.map (List.cons (encode a)) o
this :
  Primrec fun n =>
    List.foldl (fun o m => Option.bind (decode m) fun a => Option.map (List.cons (encode a)) o) (some [])
      (List.reverse (ofNat (List ℕ) n))
n✝ n : ℕ
IH :
  ∀ m ≤ n,
    encode
        (List.foldr (fun x y => Option.bind (decode x) fun a => Option.map (List.cons (encode a)) y) (some [])
          (ofNat (List ℕ) m)) =
      encode (decode m)
a : α
⊢ ∀ (o : Option (List ℕ)) (p : Option (List α)),
    encode o = encode p → encode (Option.map (List.cons (encode a)) o) = encode (Option.map (List.cons a) p)

Next tactic:
exact this _ _ (IH _ (Nat.unpair_right_le n))
instance list : Primcodable (List α) :=
  ⟨letI H := @Primcodable.prim (List ℕ) _
    have : Primrec₂ fun (a : α) (o : Option (List ℕ)) => o.map (List.cons (encode a)) :=
      option_map snd <| (list_cons' H).comp ((@Primrec.encode α _).comp (fst.comp fst)) snd
    have :
      Primrec fun n =>
        (ofNat (List ℕ) n).reverse.foldl
          (fun o m => (@decode α _ m).bind fun a => o.map (List.cons (encode a))) (some []) :=
      list_foldl' H ((list_reverse' H).comp (.ofNat (List ℕ))) (const (some []))
        (Primrec.comp₂ (bind_decode_iff.2 <| .swap this) Primrec₂.right)
    nat_iff.1 <|
      (encode_iff.2 this).of_eq fun n => by
        rw [List.foldl_reverse]
        apply Nat.case_strong_induction_on n; · simp
        intro n IH; simp
        cases' @decode α _ n.unpair.1 with a; · rfl
        simp only [decode_eq_ofNat, Option.some.injEq, Option.some_bind, Option.map_some']
        suffices :
          ∀ (o : Option (List ℕ)) (p) (_ : encode o = encode p),
            encode (Option.map (List.cons (encode a)) o) = encode (Option.map (List.cons a) p)
        exact this _ _ (IH _ (Nat.unpair_right_le n))
        

Proof state:
case this
α : Type u_1
β : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable β
H : Nat.Primrec fun n => encode (decode n) := prim
this✝ : Primrec₂ fun a o => Option.map (List.cons (encode a)) o
this :
  Primrec fun n =>
    List.foldl (fun o m => Option.bind (decode m) fun a => Option.map (List.cons (encode a)) o) (some [])
      (List.reverse (ofNat (List ℕ) n))
n✝ n : ℕ
IH :
  ∀ m ≤ n,
    encode
        (List.foldr (fun x y => Option.bind (decode x) fun a => Option.map (List.cons (encode a)) y) (some [])
          (ofNat (List ℕ) m)) =
      encode (decode m)
a : α
⊢ ∀ (o : Option (List ℕ)) (p : Option (List α)),
    encode o = encode p → encode (Option.map (List.cons (encode a)) o) = encode (Option.map (List.cons a) p)

Next tactic:
intro o p IH
instance list : Primcodable (List α) :=
  ⟨letI H := @Primcodable.prim (List ℕ) _
    have : Primrec₂ fun (a : α) (o : Option (List ℕ)) => o.map (List.cons (encode a)) :=
      option_map snd <| (list_cons' H).comp ((@Primrec.encode α _).comp (fst.comp fst)) snd
    have :
      Primrec fun n =>
        (ofNat (List ℕ) n).reverse.foldl
          (fun o m => (@decode α _ m).bind fun a => o.map (List.cons (encode a))) (some []) :=
      list_foldl' H ((list_reverse' H).comp (.ofNat (List ℕ))) (const (some []))
        (Primrec.comp₂ (bind_decode_iff.2 <| .swap this) Primrec₂.right)
    nat_iff.1 <|
      (encode_iff.2 this).of_eq fun n => by
        rw [List.foldl_reverse]
        apply Nat.case_strong_induction_on n; · simp
        intro n IH; simp
        cases' @decode α _ n.unpair.1 with a; · rfl
        simp only [decode_eq_ofNat, Option.some.injEq, Option.some_bind, Option.map_some']
        suffices :
          ∀ (o : Option (List ℕ)) (p) (_ : encode o = encode p),
            encode (Option.map (List.cons (encode a)) o) = encode (Option.map (List.cons a) p)
        exact this _ _ (IH _ (Nat.unpair_right_le n))
        intro o p IH
        

Proof state:
case this
α : Type u_1
β : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable β
H : Nat.Primrec fun n => encode (decode n) := prim
this✝ : Primrec₂ fun a o => Option.map (List.cons (encode a)) o
this :
  Primrec fun n =>
    List.foldl (fun o m => Option.bind (decode m) fun a => Option.map (List.cons (encode a)) o) (some [])
      (List.reverse (ofNat (List ℕ) n))
n✝ n : ℕ
IH✝ :
  ∀ m ≤ n,
    encode
        (List.foldr (fun x y => Option.bind (decode x) fun a => Option.map (List.cons (encode a)) y) (some [])
          (ofNat (List ℕ) m)) =
      encode (decode m)
a : α
o : Option (List ℕ)
p : Option (List α)
IH : encode o = encode p
⊢ encode (Option.map (List.cons (encode a)) o) = encode (Option.map (List.cons a) p)

Next tactic:
cases o
instance list : Primcodable (List α) :=
  ⟨letI H := @Primcodable.prim (List ℕ) _
    have : Primrec₂ fun (a : α) (o : Option (List ℕ)) => o.map (List.cons (encode a)) :=
      option_map snd <| (list_cons' H).comp ((@Primrec.encode α _).comp (fst.comp fst)) snd
    have :
      Primrec fun n =>
        (ofNat (List ℕ) n).reverse.foldl
          (fun o m => (@decode α _ m).bind fun a => o.map (List.cons (encode a))) (some []) :=
      list_foldl' H ((list_reverse' H).comp (.ofNat (List ℕ))) (const (some []))
        (Primrec.comp₂ (bind_decode_iff.2 <| .swap this) Primrec₂.right)
    nat_iff.1 <|
      (encode_iff.2 this).of_eq fun n => by
        rw [List.foldl_reverse]
        apply Nat.case_strong_induction_on n; · simp
        intro n IH; simp
        cases' @decode α _ n.unpair.1 with a; · rfl
        simp only [decode_eq_ofNat, Option.some.injEq, Option.some_bind, Option.map_some']
        suffices :
          ∀ (o : Option (List ℕ)) (p) (_ : encode o = encode p),
            encode (Option.map (List.cons (encode a)) o) = encode (Option.map (List.cons a) p)
        exact this _ _ (IH _ (Nat.unpair_right_le n))
        intro o p IH
        cases o <;> 

Proof state:
case this.none
α : Type u_1
β : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable β
H : Nat.Primrec fun n => encode (decode n) := prim
this✝ : Primrec₂ fun a o => Option.map (List.cons (encode a)) o
this :
  Primrec fun n =>
    List.foldl (fun o m => Option.bind (decode m) fun a => Option.map (List.cons (encode a)) o) (some [])
      (List.reverse (ofNat (List ℕ) n))
n✝ n : ℕ
IH✝ :
  ∀ m ≤ n,
    encode
        (List.foldr (fun x y => Option.bind (decode x) fun a => Option.map (List.cons (encode a)) y) (some [])
          (ofNat (List ℕ) m)) =
      encode (decode m)
a : α
p : Option (List α)
IH : encode none = encode p
⊢ encode (Option.map (List.cons (encode a)) none) = encode (Option.map (List.cons a) p)

Next tactic:
cases p
instance list : Primcodable (List α) :=
  ⟨letI H := @Primcodable.prim (List ℕ) _
    have : Primrec₂ fun (a : α) (o : Option (List ℕ)) => o.map (List.cons (encode a)) :=
      option_map snd <| (list_cons' H).comp ((@Primrec.encode α _).comp (fst.comp fst)) snd
    have :
      Primrec fun n =>
        (ofNat (List ℕ) n).reverse.foldl
          (fun o m => (@decode α _ m).bind fun a => o.map (List.cons (encode a))) (some []) :=
      list_foldl' H ((list_reverse' H).comp (.ofNat (List ℕ))) (const (some []))
        (Primrec.comp₂ (bind_decode_iff.2 <| .swap this) Primrec₂.right)
    nat_iff.1 <|
      (encode_iff.2 this).of_eq fun n => by
        rw [List.foldl_reverse]
        apply Nat.case_strong_induction_on n; · simp
        intro n IH; simp
        cases' @decode α _ n.unpair.1 with a; · rfl
        simp only [decode_eq_ofNat, Option.some.injEq, Option.some_bind, Option.map_some']
        suffices :
          ∀ (o : Option (List ℕ)) (p) (_ : encode o = encode p),
            encode (Option.map (List.cons (encode a)) o) = encode (Option.map (List.cons a) p)
        exact this _ _ (IH _ (Nat.unpair_right_le n))
        intro o p IH
        cases o <;> 

Proof state:
case this.some
α : Type u_1
β : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable β
H : Nat.Primrec fun n => encode (decode n) := prim
this✝ : Primrec₂ fun a o => Option.map (List.cons (encode a)) o
this :
  Primrec fun n =>
    List.foldl (fun o m => Option.bind (decode m) fun a => Option.map (List.cons (encode a)) o) (some [])
      (List.reverse (ofNat (List ℕ) n))
n✝ n : ℕ
IH✝ :
  ∀ m ≤ n,
    encode
        (List.foldr (fun x y => Option.bind (decode x) fun a => Option.map (List.cons (encode a)) y) (some [])
          (ofNat (List ℕ) m)) =
      encode (decode m)
a : α
p : Option (List α)
val✝ : List ℕ
IH : encode (some val✝) = encode p
⊢ encode (Option.map (List.cons (encode a)) (some val✝)) = encode (Option.map (List.cons a) p)

Next tactic:
cases p
instance list : Primcodable (List α) :=
  ⟨letI H := @Primcodable.prim (List ℕ) _
    have : Primrec₂ fun (a : α) (o : Option (List ℕ)) => o.map (List.cons (encode a)) :=
      option_map snd <| (list_cons' H).comp ((@Primrec.encode α _).comp (fst.comp fst)) snd
    have :
      Primrec fun n =>
        (ofNat (List ℕ) n).reverse.foldl
          (fun o m => (@decode α _ m).bind fun a => o.map (List.cons (encode a))) (some []) :=
      list_foldl' H ((list_reverse' H).comp (.ofNat (List ℕ))) (const (some []))
        (Primrec.comp₂ (bind_decode_iff.2 <| .swap this) Primrec₂.right)
    nat_iff.1 <|
      (encode_iff.2 this).of_eq fun n => by
        rw [List.foldl_reverse]
        apply Nat.case_strong_induction_on n; · simp
        intro n IH; simp
        cases' @decode α _ n.unpair.1 with a; · rfl
        simp only [decode_eq_ofNat, Option.some.injEq, Option.some_bind, Option.map_some']
        suffices :
          ∀ (o : Option (List ℕ)) (p) (_ : encode o = encode p),
            encode (Option.map (List.cons (encode a)) o) = encode (Option.map (List.cons a) p)
        exact this _ _ (IH _ (Nat.unpair_right_le n))
        intro o p IH
        cases o <;> cases p
        · 

Proof state:
case this.none.none
α : Type u_1
β : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable β
H : Nat.Primrec fun n => encode (decode n) := prim
this✝ : Primrec₂ fun a o => Option.map (List.cons (encode a)) o
this :
  Primrec fun n =>
    List.foldl (fun o m => Option.bind (decode m) fun a => Option.map (List.cons (encode a)) o) (some [])
      (List.reverse (ofNat (List ℕ) n))
n✝ n : ℕ
IH✝ :
  ∀ m ≤ n,
    encode
        (List.foldr (fun x y => Option.bind (decode x) fun a => Option.map (List.cons (encode a)) y) (some [])
          (ofNat (List ℕ) m)) =
      encode (decode m)
a : α
IH : encode none = encode none
⊢ encode (Option.map (List.cons (encode a)) none) = encode (Option.map (List.cons a) none)

Next tactic:
rfl
instance list : Primcodable (List α) :=
  ⟨letI H := @Primcodable.prim (List ℕ) _
    have : Primrec₂ fun (a : α) (o : Option (List ℕ)) => o.map (List.cons (encode a)) :=
      option_map snd <| (list_cons' H).comp ((@Primrec.encode α _).comp (fst.comp fst)) snd
    have :
      Primrec fun n =>
        (ofNat (List ℕ) n).reverse.foldl
          (fun o m => (@decode α _ m).bind fun a => o.map (List.cons (encode a))) (some []) :=
      list_foldl' H ((list_reverse' H).comp (.ofNat (List ℕ))) (const (some []))
        (Primrec.comp₂ (bind_decode_iff.2 <| .swap this) Primrec₂.right)
    nat_iff.1 <|
      (encode_iff.2 this).of_eq fun n => by
        rw [List.foldl_reverse]
        apply Nat.case_strong_induction_on n; · simp
        intro n IH; simp
        cases' @decode α _ n.unpair.1 with a; · rfl
        simp only [decode_eq_ofNat, Option.some.injEq, Option.some_bind, Option.map_some']
        suffices :
          ∀ (o : Option (List ℕ)) (p) (_ : encode o = encode p),
            encode (Option.map (List.cons (encode a)) o) = encode (Option.map (List.cons a) p)
        exact this _ _ (IH _ (Nat.unpair_right_le n))
        intro o p IH
        cases o <;> cases p
        · rfl
        · 

Proof state:
case this.none.some
α : Type u_1
β : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable β
H : Nat.Primrec fun n => encode (decode n) := prim
this✝ : Primrec₂ fun a o => Option.map (List.cons (encode a)) o
this :
  Primrec fun n =>
    List.foldl (fun o m => Option.bind (decode m) fun a => Option.map (List.cons (encode a)) o) (some [])
      (List.reverse (ofNat (List ℕ) n))
n✝ n : ℕ
IH✝ :
  ∀ m ≤ n,
    encode
        (List.foldr (fun x y => Option.bind (decode x) fun a => Option.map (List.cons (encode a)) y) (some [])
          (ofNat (List ℕ) m)) =
      encode (decode m)
a : α
val✝ : List α
IH : encode none = encode (some val✝)
⊢ encode (Option.map (List.cons (encode a)) none) = encode (Option.map (List.cons a) (some val✝))

Next tactic:
injection IH
instance list : Primcodable (List α) :=
  ⟨letI H := @Primcodable.prim (List ℕ) _
    have : Primrec₂ fun (a : α) (o : Option (List ℕ)) => o.map (List.cons (encode a)) :=
      option_map snd <| (list_cons' H).comp ((@Primrec.encode α _).comp (fst.comp fst)) snd
    have :
      Primrec fun n =>
        (ofNat (List ℕ) n).reverse.foldl
          (fun o m => (@decode α _ m).bind fun a => o.map (List.cons (encode a))) (some []) :=
      list_foldl' H ((list_reverse' H).comp (.ofNat (List ℕ))) (const (some []))
        (Primrec.comp₂ (bind_decode_iff.2 <| .swap this) Primrec₂.right)
    nat_iff.1 <|
      (encode_iff.2 this).of_eq fun n => by
        rw [List.foldl_reverse]
        apply Nat.case_strong_induction_on n; · simp
        intro n IH; simp
        cases' @decode α _ n.unpair.1 with a; · rfl
        simp only [decode_eq_ofNat, Option.some.injEq, Option.some_bind, Option.map_some']
        suffices :
          ∀ (o : Option (List ℕ)) (p) (_ : encode o = encode p),
            encode (Option.map (List.cons (encode a)) o) = encode (Option.map (List.cons a) p)
        exact this _ _ (IH _ (Nat.unpair_right_le n))
        intro o p IH
        cases o <;> cases p
        · rfl
        · injection IH
        · 

Proof state:
case this.some.none
α : Type u_1
β : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable β
H : Nat.Primrec fun n => encode (decode n) := prim
this✝ : Primrec₂ fun a o => Option.map (List.cons (encode a)) o
this :
  Primrec fun n =>
    List.foldl (fun o m => Option.bind (decode m) fun a => Option.map (List.cons (encode a)) o) (some [])
      (List.reverse (ofNat (List ℕ) n))
n✝ n : ℕ
IH✝ :
  ∀ m ≤ n,
    encode
        (List.foldr (fun x y => Option.bind (decode x) fun a => Option.map (List.cons (encode a)) y) (some [])
          (ofNat (List ℕ) m)) =
      encode (decode m)
a : α
val✝ : List ℕ
IH : encode (some val✝) = encode none
⊢ encode (Option.map (List.cons (encode a)) (some val✝)) = encode (Option.map (List.cons a) none)

Next tactic:
injection IH
instance list : Primcodable (List α) :=
  ⟨letI H := @Primcodable.prim (List ℕ) _
    have : Primrec₂ fun (a : α) (o : Option (List ℕ)) => o.map (List.cons (encode a)) :=
      option_map snd <| (list_cons' H).comp ((@Primrec.encode α _).comp (fst.comp fst)) snd
    have :
      Primrec fun n =>
        (ofNat (List ℕ) n).reverse.foldl
          (fun o m => (@decode α _ m).bind fun a => o.map (List.cons (encode a))) (some []) :=
      list_foldl' H ((list_reverse' H).comp (.ofNat (List ℕ))) (const (some []))
        (Primrec.comp₂ (bind_decode_iff.2 <| .swap this) Primrec₂.right)
    nat_iff.1 <|
      (encode_iff.2 this).of_eq fun n => by
        rw [List.foldl_reverse]
        apply Nat.case_strong_induction_on n; · simp
        intro n IH; simp
        cases' @decode α _ n.unpair.1 with a; · rfl
        simp only [decode_eq_ofNat, Option.some.injEq, Option.some_bind, Option.map_some']
        suffices :
          ∀ (o : Option (List ℕ)) (p) (_ : encode o = encode p),
            encode (Option.map (List.cons (encode a)) o) = encode (Option.map (List.cons a) p)
        exact this _ _ (IH _ (Nat.unpair_right_le n))
        intro o p IH
        cases o <;> cases p
        · rfl
        · injection IH
        · injection IH
        · 

Proof state:
case this.some.some
α : Type u_1
β : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable β
H : Nat.Primrec fun n => encode (decode n) := prim
this✝ : Primrec₂ fun a o => Option.map (List.cons (encode a)) o
this :
  Primrec fun n =>
    List.foldl (fun o m => Option.bind (decode m) fun a => Option.map (List.cons (encode a)) o) (some [])
      (List.reverse (ofNat (List ℕ) n))
n✝ n : ℕ
IH✝ :
  ∀ m ≤ n,
    encode
        (List.foldr (fun x y => Option.bind (decode x) fun a => Option.map (List.cons (encode a)) y) (some [])
          (ofNat (List ℕ) m)) =
      encode (decode m)
a : α
val✝¹ : List ℕ
val✝ : List α
IH : encode (some val✝¹) = encode (some val✝)
⊢ encode (Option.map (List.cons (encode a)) (some val✝¹)) = encode (Option.map (List.cons a) (some val✝))

Next tactic:
exact congr_arg (fun k => (Nat.pair (encode a) k).succ.succ) (Nat.succ.inj IH)
theorem sum_casesOn {f : α → Sum β γ} {g : α → β → σ} {h : α → γ → σ} (hf : Primrec f)
    (hg : Primrec₂ g) (hh : Primrec₂ h) : @Primrec _ σ _ _ fun a => Sum.casesOn (f a) (g a) (h a) :=
  option_some_iff.1 <|
    (cond (nat_bodd.comp <| encode_iff.2 hf)
          (option_map (Primrec.decode.comp <| nat_div2.comp <| encode_iff.2 hf) hh)
          (option_map (Primrec.decode.comp <| nat_div2.comp <| encode_iff.2 hf) 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 : Primrec f
hg : Primrec₂ g
hh : Primrec₂ h
a : α
⊢ (bif Nat.bodd (encode (f a)) then Option.map (h a) (decode (Nat.div2 (encode (f a))))
    else Option.map (g a) (decode (Nat.div2 (encode (f a))))) =
    some (Sum.casesOn (f a) (g a) (h a))

Next tactic:
cases' f a with b c
theorem sum_casesOn {f : α → Sum β γ} {g : α → β → σ} {h : α → γ → σ} (hf : Primrec f)
    (hg : Primrec₂ g) (hh : Primrec₂ h) : @Primrec _ σ _ _ fun a => Sum.casesOn (f a) (g a) (h a) :=
  option_some_iff.1 <|
    (cond (nat_bodd.comp <| encode_iff.2 hf)
          (option_map (Primrec.decode.comp <| nat_div2.comp <| encode_iff.2 hf) hh)
          (option_map (Primrec.decode.comp <| nat_div2.comp <| encode_iff.2 hf) hg)).of_eq
      fun a => by cases' f a with b c <;> 

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 : Primrec f
hg : Primrec₂ g
hh : Primrec₂ h
a : α
b : β
⊢ (bif Nat.bodd (encode (Sum.inl b)) then Option.map (h a) (decode (Nat.div2 (encode (Sum.inl b))))
    else Option.map (g a) (decode (Nat.div2 (encode (Sum.inl b))))) =
    some (Sum.casesOn (Sum.inl b) (g a) (h a))

Next tactic:
simp [Nat.div2_val, encodek]
theorem sum_casesOn {f : α → Sum β γ} {g : α → β → σ} {h : α → γ → σ} (hf : Primrec f)
    (hg : Primrec₂ g) (hh : Primrec₂ h) : @Primrec _ σ _ _ fun a => Sum.casesOn (f a) (g a) (h a) :=
  option_some_iff.1 <|
    (cond (nat_bodd.comp <| encode_iff.2 hf)
          (option_map (Primrec.decode.comp <| nat_div2.comp <| encode_iff.2 hf) hh)
          (option_map (Primrec.decode.comp <| nat_div2.comp <| encode_iff.2 hf) hg)).of_eq
      fun a => by cases' f a with b c <;> 

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 : Primrec f
hg : Primrec₂ g
hh : Primrec₂ h
a : α
c : γ
⊢ (bif Nat.bodd (encode (Sum.inr c)) then Option.map (h a) (decode (Nat.div2 (encode (Sum.inr c))))
    else Option.map (g a) (decode (Nat.div2 (encode (Sum.inr c))))) =
    some (Sum.casesOn (Sum.inr c) (g a) (h a))

Next tactic:
simp [Nat.div2_val, encodek]
theorem list_foldr {f : α → List β} {g : α → σ} {h : α → β × σ → σ} (hf : Primrec f)
    (hg : Primrec g) (hh : Primrec₂ h) :
    Primrec fun a => (f a).foldr (fun b s => h a (b, s)) (g a) :=
  (list_foldl (list_reverse.comp hf) hg <| to₂ <| hh.comp fst <| (pair snd fst).comp snd).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 : α → List β
g : α → σ
h : α → β × σ → σ
hf : Primrec f
hg : Primrec g
hh : Primrec₂ h
a : α
⊢ List.foldl (fun s b => h (a, s, b).1 ((a, s, b).2.2, (a, s, b).2.1)) (g a) (List.reverse (f a)) =
    List.foldr (fun b s => h a (b, s)) (g a) (f a)

Next tactic:
simp [List.foldl_reverse]