l3lab/ntp-mathlib huggingface dataset:
private theorem list_reverse' :
    haveI := prim H
    Primrec (@List.reverse β) :=
  letI := prim H
  (list_foldl' H .id (const []) <| to₂ <| ((list_cons' H).comp snd fst).comp snd).of_eq
    (suffices ∀ l r, List.foldl (fun (s : List β) (b : β) => b :: s) r l = List.reverseAux l r from
      fun l => this l []
    fun l => by 

Proof state:
α : Type u_1
β : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
H : Nat.Primrec fun n => encode (decode n)
this : Primcodable (List β) := prim H
l : List β
⊢ ∀ (r : List β), List.foldl (fun s b => b :: s) r l = List.reverseAux l r

Next tactic:
induction l
private theorem list_reverse' :
    haveI := prim H
    Primrec (@List.reverse β) :=
  letI := prim H
  (list_foldl' H .id (const []) <| to₂ <| ((list_cons' H).comp snd fst).comp snd).of_eq
    (suffices ∀ l r, List.foldl (fun (s : List β) (b : β) => b :: s) r l = List.reverseAux l r from
      fun l => this l []
    fun l => by induction l <;> 

Proof state:
case nil
α : Type u_1
β : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
H : Nat.Primrec fun n => encode (decode n)
this : Primcodable (List β) := prim H
⊢ ∀ (r : List β), List.foldl (fun s b => b :: s) r [] = List.reverseAux [] r

Next tactic:
simp [*, List.reverseAux]
private theorem list_reverse' :
    haveI := prim H
    Primrec (@List.reverse β) :=
  letI := prim H
  (list_foldl' H .id (const []) <| to₂ <| ((list_cons' H).comp snd fst).comp snd).of_eq
    (suffices ∀ l r, List.foldl (fun (s : List β) (b : β) => b :: s) r l = List.reverseAux l r from
      fun l => this l []
    fun l => by induction l <;> 

Proof state:
case cons
α : Type u_1
β : Type u_2
σ : Type u_3
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
H : Nat.Primrec fun n => encode (decode n)
this : Primcodable (List β) := prim H
head✝ : β
tail✝ : List β
tail_ih✝ : ∀ (r : List β), List.foldl (fun s b => b :: s) r tail✝ = List.reverseAux tail✝ r
⊢ ∀ (r : List β), List.foldl (fun s b => b :: s) r (head✝ :: tail✝) = List.reverseAux (head✝ :: tail✝) r

Next tactic:
simp [*, List.reverseAux]
instance sum : Primcodable (Sum α β) :=
  ⟨Primrec.nat_iff.1 <|
      (encode_iff.2
            (cond nat_bodd
              (((@Primrec.decode β _).comp nat_div2).option_map <|
                to₂ <| nat_double_succ.comp (Primrec.encode.comp snd))
              (((@Primrec.decode α _).comp nat_div2).option_map <|
                to₂ <| nat_double.comp (Primrec.encode.comp snd)))).of_eq
        fun n =>
        show _ = encode (decodeSum n) by
          

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable β
n : ℕ
⊢ encode
      (bif Nat.bodd n then Option.map (fun b => 2 * encode (n, b).2 + 1) (decode (Nat.div2 n))
      else Option.map (fun b => 2 * encode (n, b).2) (decode (Nat.div2 n))) =
    encode (decodeSum n)

Next tactic:
simp only [decodeSum, Nat.boddDiv2_eq]
instance sum : Primcodable (Sum α β) :=
  ⟨Primrec.nat_iff.1 <|
      (encode_iff.2
            (cond nat_bodd
              (((@Primrec.decode β _).comp nat_div2).option_map <|
                to₂ <| nat_double_succ.comp (Primrec.encode.comp snd))
              (((@Primrec.decode α _).comp nat_div2).option_map <|
                to₂ <| nat_double.comp (Primrec.encode.comp snd)))).of_eq
        fun n =>
        show _ = encode (decodeSum n) by
          simp only [decodeSum, Nat.boddDiv2_eq]
          

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable β
n : ℕ
⊢ encode
      (bif Nat.bodd n then Option.map (fun b => 2 * encode b + 1) (decode (Nat.div2 n))
      else Option.map (fun b => 2 * encode b) (decode (Nat.div2 n))) =
    encode
      (match (Nat.bodd n, Nat.div2 n) with
      | (false, m) => Option.map Sum.inl (decode m)
      | (fst, m) => Option.map Sum.inr (decode m))

Next tactic:
cases Nat.bodd n
instance sum : Primcodable (Sum α β) :=
  ⟨Primrec.nat_iff.1 <|
      (encode_iff.2
            (cond nat_bodd
              (((@Primrec.decode β _).comp nat_div2).option_map <|
                to₂ <| nat_double_succ.comp (Primrec.encode.comp snd))
              (((@Primrec.decode α _).comp nat_div2).option_map <|
                to₂ <| nat_double.comp (Primrec.encode.comp snd)))).of_eq
        fun n =>
        show _ = encode (decodeSum n) by
          simp only [decodeSum, Nat.boddDiv2_eq]
          cases Nat.bodd n <;> 

Proof state:
case false
α : Type u_1
β : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable β
n : ℕ
⊢ encode
      (bif false then Option.map (fun b => 2 * encode b + 1) (decode (Nat.div2 n))
      else Option.map (fun b => 2 * encode b) (decode (Nat.div2 n))) =
    encode
      (match (false, Nat.div2 n) with
      | (false, m) => Option.map Sum.inl (decode m)
      | (fst, m) => Option.map Sum.inr (decode m))

Next tactic:
simp [decodeSum]
instance sum : Primcodable (Sum α β) :=
  ⟨Primrec.nat_iff.1 <|
      (encode_iff.2
            (cond nat_bodd
              (((@Primrec.decode β _).comp nat_div2).option_map <|
                to₂ <| nat_double_succ.comp (Primrec.encode.comp snd))
              (((@Primrec.decode α _).comp nat_div2).option_map <|
                to₂ <| nat_double.comp (Primrec.encode.comp snd)))).of_eq
        fun n =>
        show _ = encode (decodeSum n) by
          simp only [decodeSum, Nat.boddDiv2_eq]
          cases Nat.bodd n <;> 

Proof state:
case true
α : Type u_1
β : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable β
n : ℕ
⊢ encode
      (bif true then Option.map (fun b => 2 * encode b + 1) (decode (Nat.div2 n))
      else Option.map (fun b => 2 * encode b) (decode (Nat.div2 n))) =
    encode
      (match (true, Nat.div2 n) with
      | (false, m) => Option.map Sum.inl (decode m)
      | (fst, m) => Option.map Sum.inr (decode m))

Next tactic:
simp [decodeSum]
instance sum : Primcodable (Sum α β) :=
  ⟨Primrec.nat_iff.1 <|
      (encode_iff.2
            (cond nat_bodd
              (((@Primrec.decode β _).comp nat_div2).option_map <|
                to₂ <| nat_double_succ.comp (Primrec.encode.comp snd))
              (((@Primrec.decode α _).comp nat_div2).option_map <|
                to₂ <| nat_double.comp (Primrec.encode.comp snd)))).of_eq
        fun n =>
        show _ = encode (decodeSum n) by
          simp only [decodeSum, Nat.boddDiv2_eq]
          cases Nat.bodd n <;> simp [decodeSum]
          · 

Proof state:
case false
α : Type u_1
β : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable β
n : ℕ
⊢ encode (Option.map (fun b => 2 * encode b) (decode (Nat.div2 n))) = encode (Option.map Sum.inl (decode (Nat.div2 n)))

Next tactic:
cases @decode α _ n.div2
instance sum : Primcodable (Sum α β) :=
  ⟨Primrec.nat_iff.1 <|
      (encode_iff.2
            (cond nat_bodd
              (((@Primrec.decode β _).comp nat_div2).option_map <|
                to₂ <| nat_double_succ.comp (Primrec.encode.comp snd))
              (((@Primrec.decode α _).comp nat_div2).option_map <|
                to₂ <| nat_double.comp (Primrec.encode.comp snd)))).of_eq
        fun n =>
        show _ = encode (decodeSum n) by
          simp only [decodeSum, Nat.boddDiv2_eq]
          cases Nat.bodd n <;> simp [decodeSum]
          · cases @decode α _ n.div2 <;> 

Proof state:
case false.none
α : Type u_1
β : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable β
n : ℕ
⊢ encode (Option.map (fun b => 2 * encode b) none) = encode (Option.map Sum.inl none)

Next tactic:
rfl
instance sum : Primcodable (Sum α β) :=
  ⟨Primrec.nat_iff.1 <|
      (encode_iff.2
            (cond nat_bodd
              (((@Primrec.decode β _).comp nat_div2).option_map <|
                to₂ <| nat_double_succ.comp (Primrec.encode.comp snd))
              (((@Primrec.decode α _).comp nat_div2).option_map <|
                to₂ <| nat_double.comp (Primrec.encode.comp snd)))).of_eq
        fun n =>
        show _ = encode (decodeSum n) by
          simp only [decodeSum, Nat.boddDiv2_eq]
          cases Nat.bodd n <;> simp [decodeSum]
          · cases @decode α _ n.div2 <;> 

Proof state:
case false.some
α : Type u_1
β : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable β
n : ℕ
val✝ : α
⊢ encode (Option.map (fun b => 2 * encode b) (some val✝)) = encode (Option.map Sum.inl (some val✝))

Next tactic:
rfl
instance sum : Primcodable (Sum α β) :=
  ⟨Primrec.nat_iff.1 <|
      (encode_iff.2
            (cond nat_bodd
              (((@Primrec.decode β _).comp nat_div2).option_map <|
                to₂ <| nat_double_succ.comp (Primrec.encode.comp snd))
              (((@Primrec.decode α _).comp nat_div2).option_map <|
                to₂ <| nat_double.comp (Primrec.encode.comp snd)))).of_eq
        fun n =>
        show _ = encode (decodeSum n) by
          simp only [decodeSum, Nat.boddDiv2_eq]
          cases Nat.bodd n <;> simp [decodeSum]
          · cases @decode α _ n.div2 <;> rfl
          · 

Proof state:
case true
α : Type u_1
β : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable β
n : ℕ
⊢ encode (Option.map (fun b => 2 * encode b + 1) (decode (Nat.div2 n))) =
    encode (Option.map Sum.inr (decode (Nat.div2 n)))

Next tactic:
cases @decode β _ n.div2
instance sum : Primcodable (Sum α β) :=
  ⟨Primrec.nat_iff.1 <|
      (encode_iff.2
            (cond nat_bodd
              (((@Primrec.decode β _).comp nat_div2).option_map <|
                to₂ <| nat_double_succ.comp (Primrec.encode.comp snd))
              (((@Primrec.decode α _).comp nat_div2).option_map <|
                to₂ <| nat_double.comp (Primrec.encode.comp snd)))).of_eq
        fun n =>
        show _ = encode (decodeSum n) by
          simp only [decodeSum, Nat.boddDiv2_eq]
          cases Nat.bodd n <;> simp [decodeSum]
          · cases @decode α _ n.div2 <;> rfl
          · cases @decode β _ n.div2 <;> 

Proof state:
case true.none
α : Type u_1
β : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable β
n : ℕ
⊢ encode (Option.map (fun b => 2 * encode b + 1) none) = encode (Option.map Sum.inr none)

Next tactic:
rfl
instance sum : Primcodable (Sum α β) :=
  ⟨Primrec.nat_iff.1 <|
      (encode_iff.2
            (cond nat_bodd
              (((@Primrec.decode β _).comp nat_div2).option_map <|
                to₂ <| nat_double_succ.comp (Primrec.encode.comp snd))
              (((@Primrec.decode α _).comp nat_div2).option_map <|
                to₂ <| nat_double.comp (Primrec.encode.comp snd)))).of_eq
        fun n =>
        show _ = encode (decodeSum n) by
          simp only [decodeSum, Nat.boddDiv2_eq]
          cases Nat.bodd n <;> simp [decodeSum]
          · cases @decode α _ n.div2 <;> rfl
          · cases @decode β _ n.div2 <;> 

Proof state:
case true.some
α : Type u_1
β : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable β
n : ℕ
val✝ : β
⊢ encode (Option.map (fun b => 2 * encode b + 1) (some val✝)) = encode (Option.map Sum.inr (some val✝))

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
        

Proof state:
α : 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 : ℕ
⊢ encode
      (List.foldl (fun o m => Option.bind (decode m) fun a => Option.map (List.cons (encode a)) o) (some [])
        (List.reverse (ofNat (List ℕ) n))) =
    encode (decode n)

Next tactic:
rw [List.foldl_reverse]
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]
        

Proof state:
α : 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 : ℕ
⊢ encode
      (List.foldr (fun x y => Option.bind (decode x) fun a => Option.map (List.cons (encode a)) y) (some [])
        (ofNat (List ℕ) n)) =
    encode (decode n)

Next tactic:
apply Nat.case_strong_induction_on 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; · 

Proof state:
case hz
α : 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 : ℕ
⊢ encode
      (List.foldr (fun x y => Option.bind (decode x) fun a => Option.map (List.cons (encode a)) y) (some [])
        (ofNat (List ℕ) 0)) =
    encode (decode 0)

Next tactic:
simp
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
        

Proof state:
case hi
α : 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 : ℕ),
    (∀ 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)) →
      encode
          (List.foldr (fun x y => Option.bind (decode x) fun a => Option.map (List.cons (encode a)) y) (some [])
            (ofNat (List ℕ) (Nat.succ n))) =
        encode (decode (Nat.succ n))

Next tactic:
intro n 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; 

Proof state:
case hi
α : 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)
⊢ encode
      (List.foldr (fun x y => Option.bind (decode x) fun a => Option.map (List.cons (encode a)) y) (some [])
        (ofNat (List ℕ) (Nat.succ n))) =
    encode (decode (Nat.succ n))

Next tactic:
simp
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
        

Proof state:
case hi
α : 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)
⊢ encode
      (Option.bind (decode (Nat.unpair n).1) fun a =>
        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 (Option.map (fun x x_1 => x :: x_1) (decode (Nat.unpair n).1)) fun x => decode (Nat.unpair n).2)

Next tactic:
cases' @decode α _ n.unpair.1 with a
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; · 

Proof state:
case hi.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)
⊢ encode
      (Option.bind none fun a =>
        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 (Option.map (fun x x_1 => x :: x_1) none) fun x => decode (Nat.unpair n).2)

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
        

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.bind (some a) fun a =>
        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 (Option.map (fun x x_1 => x :: x_1) (some a)) fun x => decode (Nat.unpair n).2)

Next tactic:
simp only [decode_eq_ofNat, Option.some.injEq, Option.some_bind, Option.map_some']