Theorem: Computable.bind_decode_iff
File: Mathlib/Computability/Partrec.lean

tactic: simp
state_before: α : Type u_2
β : Type u_3
γ : Type ?u.145328
σ : Type u_1
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → β → Option σ
hf : Computable₂ fun a n => Option.bind (decode n) (f a)
n : ℕ
⊢ (Part.bind ↑(decode n) fun a =>
      map encode
        ((fun a =>
            Part.bind
              (do
                let n ← (↑fun n => encode (decode n)) a.snd
                ↑(Nat.ppred n))
              ↑fun b => (fun a n => Option.bind (decode n) (f a)) (a, b).fst.fst (a, b).fst.snd)
          a)) =
    Part.bind ↑(decode n) fun a => map encode ((↑fun p => f p.fst p.snd) a)

tactic: cases decode (α := α) n.unpair.1 <;> simp
state_before: α : Type u_2
β : Type u_3
γ : Type ?u.145328
σ : Type u_1
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → β → Option σ
hf : Computable₂ fun a n => Option.bind (decode n) (f a)
n : ℕ
⊢ (Part.bind ↑(Option.bind (decode (Nat.unpair n).fst) fun a => Option.some (a, (Nat.unpair n).snd)) fun a =>
      Part.bind ↑(Nat.ppred (encode (decode a.snd))) fun y =>
        Part.some (encode (Option.bind (decode a.snd) (f a.fst)))) =
    Part.bind ↑(Option.bind (decode (Nat.unpair n).fst) fun a => Option.map (Prod.mk a) (decode (Nat.unpair n).snd))
      fun a => Part.some (encode (f a.fst a.snd))

tactic: cases decode (α := β) n.unpair.2 <;> simp
state_before: case some
α : Type u_2
β : Type u_3
γ : Type ?u.145328
σ : Type u_1
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → β → Option σ
hf : Computable₂ fun a n => Option.bind (decode n) (f a)
n : ℕ
val✝ : α
⊢ (Part.bind ↑(Nat.ppred (encode (decode (Nat.unpair n).snd))) fun y =>
      Part.some (encode (Option.bind (decode (Nat.unpair n).snd) (f val✝)))) =
    Part.bind ↑(Option.map (Prod.mk val✝) (decode (Nat.unpair n).snd)) fun a => Part.some (encode (f a.fst a.snd))

tactic: have :
  Partrec fun a : α × ℕ =>
    (encode (decode (α := β) a.2)).casesOn (some Option.none)
      fun n => Part.map (f a.1) (decode (α := β) n) :=
  Partrec.nat_casesOn_right
    (h := fun (a : α × ℕ) (n : ℕ) ↦ map (fun b ↦ f a.1 b) (Part.ofOption (decode n)))
    (Primrec.encdec.to_comp.comp snd) (const Option.none)
    ((ofOption (Computable.decode.comp snd)).map (hf.comp (fst.comp <| fst.comp fst) snd).to₂)
state_before: α : Type u_2
β : Type u_3
γ : Type ?u.145328
σ : Type u_1
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → β → Option σ
hf : Computable₂ f
⊢ Computable₂ fun a n => Option.bind (decode n) (f a)

tactic: refine' this.of_eq fun a => _
state_before: α : Type u_2
β : Type u_3
γ : Type ?u.145328
σ : Type u_1
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → β → Option σ
hf : Computable₂ f
this : Partrec fun a => Nat.casesOn (encode (decode a.snd)) (Part.some Option.none) fun n => map (f a.fst) ↑(decode n)
⊢ Computable₂ fun a n => Option.bind (decode n) (f a)

tactic: simp
state_before: α : Type u_2
β : Type u_3
γ : Type ?u.145328
σ : Type u_1
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → β → Option σ
hf : Computable₂ f
this : Partrec fun a => Nat.casesOn (encode (decode a.snd)) (Part.some Option.none) fun n => map (f a.fst) ↑(decode n)
a : α × ℕ
⊢ (Nat.casesOn (encode (decode a.snd)) (Part.some Option.none) fun n => map (f a.fst) ↑(decode n)) =
    (↑fun p => (fun a n => Option.bind (decode n) (f a)) p.fst p.snd) a

tactic: cases decode (α := β) a.2 <;> simp [encodek]
state_before: α : Type u_2
β : Type u_3
γ : Type ?u.145328
σ : Type u_1
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → β → Option σ
hf : Computable₂ f
this : Partrec fun a => Nat.casesOn (encode (decode a.snd)) (Part.some Option.none) fun n => map (f a.fst) ↑(decode n)
a : α × ℕ
⊢ Nat.rec (Part.some Option.none) (fun n n_ih => map (f a.fst) ↑(decode n)) (encode (decode a.snd)) =
    Part.some (Option.bind (decode a.snd) (f a.fst))