Theorem: interpUB'_bind (MLIR/Semantics/UB.lean)

State before:
T : Type
E : Type → Type
R : Type
t : Fitree (UBE +' E) T
k : T → Fitree (UBE +' E) R
⊢ interpUB' (Fitree.bind t k) =
    Fitree.bind (interpUB' t) fun x =>
      match x with
      | Except.error ε => Fitree.ret (Except.error ε)
      | Except.ok x => interpUB' (k x)
Tactic:
induction t with
| Ret _ => rfl
| Vis _ _ ih =>
    simp [interpUB', Fitree.interpExcept] at *
    simp [Fitree.interp, Fitree.bind, Bind.bind]
    simp [ExceptT.bind, ExceptT.mk, ExceptT.bindCont]
    have fequal2 α β (f g: α → β) x y: f = g → x = y → f x = g y :=
      fun h₁ h₂ => by simp [h₁, h₂]
    apply fequal2; rfl; funext x
    cases x <;> simp [ih]
State after:
no goals

State before:
case Ret
T : Type
E : Type → Type
R : Type
k : T → Fitree (UBE +' E) R
r✝ : T
⊢ interpUB' (Fitree.bind (Fitree.Ret r✝) k) =
    Fitree.bind (interpUB' (Fitree.Ret r✝)) fun x =>
      match x with
      | Except.error ε => Fitree.ret (Except.error ε)
      | Except.ok x => interpUB' (k x)
Tactic:
rfl
State after:
no goals

State before:
case Vis
T : Type
E : Type → Type
R : Type
k : T → Fitree (UBE +' E) R
T✝ : Type
e✝ : sum1 UBE E T✝
k✝ : T✝ → Fitree (UBE +' E) T
ih :
  ∀ (a : T✝),
    interpUB' (Fitree.bind (k✝ a) k) =
      Fitree.bind (interpUB' (k✝ a)) fun x =>
        match x with
        | Except.error ε => Fitree.ret (Except.error ε)
        | Except.ok x => interpUB' (k x)
⊢ interpUB' (Fitree.bind (Fitree.Vis e✝ k✝) k) =
    Fitree.bind (interpUB' (Fitree.Vis e✝ k✝)) fun x =>
      match x with
      | Except.error ε => Fitree.ret (Except.error ε)
      | Except.ok x => interpUB' (k x)
Tactic:
simp [interpUB', Fitree.interpExcept] at *
State after:
case Vis
T : Type
E : Type → Type
R : Type
k : T → Fitree (UBE +' E) R
T✝ : Type
e✝ : sum1 UBE E T✝
k✝ : T✝ → Fitree (UBE +' E) T
ih :
  ∀ (a : T✝),
    Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k) =
      Fitree.bind (Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)) fun x =>
        match x with
        | Except.error ε => Fitree.ret (Except.error ε)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
⊢ Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (Fitree.Vis e✝ k✝) k) =
    Fitree.bind (Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.Vis e✝ k✝)) fun x =>
      match x with
      | Except.error ε => Fitree.ret (Except.error ε)
      | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)

State before:
case Vis
T : Type
E : Type → Type
R : Type
k : T → Fitree (UBE +' E) R
T✝ : Type
e✝ : sum1 UBE E T✝
k✝ : T✝ → Fitree (UBE +' E) T
ih :
  ∀ (a : T✝),
    Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k) =
      Fitree.bind (Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)) fun x =>
        match x with
        | Except.error ε => Fitree.ret (Except.error ε)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
⊢ Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (Fitree.Vis e✝ k✝) k) =
    Fitree.bind (Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.Vis e✝ k✝)) fun x =>
      match x with
      | Except.error ε => Fitree.ret (Except.error ε)
      | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
Tactic:
simp [Fitree.interp, Fitree.bind, Bind.bind]
State after:
case Vis
T : Type
E : Type → Type
R : Type
k : T → Fitree (UBE +' E) R
T✝ : Type
e✝ : sum1 UBE E T✝
k✝ : T✝ → Fitree (UBE +' E) T
ih :
  ∀ (a : T✝),
    Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k) =
      Fitree.bind (Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)) fun x =>
        match x with
        | Except.error ε => Fitree.ret (Except.error ε)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
⊢ Fitree.bind (Fitree.case UBE.handle Fitree.liftHandler T✝ e✝)
      (ExceptT.bindCont fun t => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ t) k)) =
    Fitree.bind (Fitree.case UBE.handle Fitree.liftHandler T✝ e✝) fun x =>
      Fitree.bind (ExceptT.bindCont (fun t => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ t)) x)
        fun x =>
        match x with
        | Except.error ε => Fitree.ret (Except.error ε)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)

State before:
case Vis
T : Type
E : Type → Type
R : Type
k : T → Fitree (UBE +' E) R
T✝ : Type
e✝ : sum1 UBE E T✝
k✝ : T✝ → Fitree (UBE +' E) T
ih :
  ∀ (a : T✝),
    Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k) =
      Fitree.bind (Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)) fun x =>
        match x with
        | Except.error ε => Fitree.ret (Except.error ε)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
⊢ Fitree.bind (Fitree.case UBE.handle Fitree.liftHandler T✝ e✝)
      (ExceptT.bindCont fun t => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ t) k)) =
    Fitree.bind (Fitree.case UBE.handle Fitree.liftHandler T✝ e✝) fun x =>
      Fitree.bind (ExceptT.bindCont (fun t => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ t)) x)
        fun x =>
        match x with
        | Except.error ε => Fitree.ret (Except.error ε)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
Tactic:
simp [ExceptT.bind, ExceptT.mk, ExceptT.bindCont]
State after:
case Vis
T : Type
E : Type → Type
R : Type
k : T → Fitree (UBE +' E) R
T✝ : Type
e✝ : sum1 UBE E T✝
k✝ : T✝ → Fitree (UBE +' E) T
ih :
  ∀ (a : T✝),
    Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k) =
      Fitree.bind (Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)) fun x =>
        match x with
        | Except.error ε => Fitree.ret (Except.error ε)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
⊢ (Fitree.bind (Fitree.case UBE.handle Fitree.liftHandler T✝ e✝) fun x =>
      match x with
      | Except.ok a => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k)
      | Except.error e => Fitree.ret (Except.error e)) =
    Fitree.bind (Fitree.case UBE.handle Fitree.liftHandler T✝ e✝) fun x =>
      Fitree.bind
        (match x with
        | Except.ok a => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)
        | Except.error e => Fitree.ret (Except.error e))
        fun x =>
        match x with
        | Except.error e => Fitree.ret (Except.error e)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)

State before:
case Vis
T : Type
E : Type → Type
R : Type
k : T → Fitree (UBE +' E) R
T✝ : Type
e✝ : sum1 UBE E T✝
k✝ : T✝ → Fitree (UBE +' E) T
ih :
  ∀ (a : T✝),
    Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k) =
      Fitree.bind (Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)) fun x =>
        match x with
        | Except.error ε => Fitree.ret (Except.error ε)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
⊢ (Fitree.bind (Fitree.case UBE.handle Fitree.liftHandler T✝ e✝) fun x =>
      match x with
      | Except.ok a => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k)
      | Except.error e => Fitree.ret (Except.error e)) =
    Fitree.bind (Fitree.case UBE.handle Fitree.liftHandler T✝ e✝) fun x =>
      Fitree.bind
        (match x with
        | Except.ok a => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)
        | Except.error e => Fitree.ret (Except.error e))
        fun x =>
        match x with
        | Except.error e => Fitree.ret (Except.error e)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
Tactic:
have fequal2 α β (f g: α → β) x y: f = g → x = y → f x = g y :=
  fun h₁ h₂ => by simp [h₁, h₂]
State after:
case Vis
T : Type
E : Type → Type
R : Type
k : T → Fitree (UBE +' E) R
T✝ : Type
e✝ : sum1 UBE E T✝
k✝ : T✝ → Fitree (UBE +' E) T
ih :
  ∀ (a : T✝),
    Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k) =
      Fitree.bind (Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)) fun x =>
        match x with
        | Except.error ε => Fitree.ret (Except.error ε)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
fequal2 : ∀ (α : Sort ?u.10648) (β : Sort ?u.10649) (f g : α → β) (x y : α), f = g → x = y → f x = g y
⊢ (Fitree.bind (Fitree.case UBE.handle Fitree.liftHandler T✝ e✝) fun x =>
      match x with
      | Except.ok a => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k)
      | Except.error e => Fitree.ret (Except.error e)) =
    Fitree.bind (Fitree.case UBE.handle Fitree.liftHandler T✝ e✝) fun x =>
      Fitree.bind
        (match x with
        | Except.ok a => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)
        | Except.error e => Fitree.ret (Except.error e))
        fun x =>
        match x with
        | Except.error e => Fitree.ret (Except.error e)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)

State before:
case Vis
T : Type
E : Type → Type
R : Type
k : T → Fitree (UBE +' E) R
T✝ : Type
e✝ : sum1 UBE E T✝
k✝ : T✝ → Fitree (UBE +' E) T
ih :
  ∀ (a : T✝),
    Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k) =
      Fitree.bind (Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)) fun x =>
        match x with
        | Except.error ε => Fitree.ret (Except.error ε)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
fequal2 : ∀ (α : Sort ?u.10648) (β : Sort ?u.10649) (f g : α → β) (x y : α), f = g → x = y → f x = g y
⊢ (Fitree.bind (Fitree.case UBE.handle Fitree.liftHandler T✝ e✝) fun x =>
      match x with
      | Except.ok a => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k)
      | Except.error e => Fitree.ret (Except.error e)) =
    Fitree.bind (Fitree.case UBE.handle Fitree.liftHandler T✝ e✝) fun x =>
      Fitree.bind
        (match x with
        | Except.ok a => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)
        | Except.error e => Fitree.ret (Except.error e))
        fun x =>
        match x with
        | Except.error e => Fitree.ret (Except.error e)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
Tactic:
apply fequal2
State after:
case Vis.a
T : Type
E : Type → Type
R : Type
k : T → Fitree (UBE +' E) R
T✝ : Type
e✝ : sum1 UBE E T✝
k✝ : T✝ → Fitree (UBE +' E) T
ih :
  ∀ (a : T✝),
    Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k) =
      Fitree.bind (Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)) fun x =>
        match x with
        | Except.error ε => Fitree.ret (Except.error ε)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
fequal2 : ∀ (α β : Type 1) (f g : α → β) (x y : α), f = g → x = y → f x = g y
⊢ Fitree.bind (Fitree.case UBE.handle Fitree.liftHandler T✝ e✝) =
    Fitree.bind (Fitree.case UBE.handle Fitree.liftHandler T✝ e✝)

case Vis.a
T : Type
E : Type → Type
R : Type
k : T → Fitree (UBE +' E) R
T✝ : Type
e✝ : sum1 UBE E T✝
k✝ : T✝ → Fitree (UBE +' E) T
ih :
  ∀ (a : T✝),
    Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k) =
      Fitree.bind (Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)) fun x =>
        match x with
        | Except.error ε => Fitree.ret (Except.error ε)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
fequal2 : ∀ (α β : Type 1) (f g : α → β) (x y : α), f = g → x = y → f x = g y
⊢ (fun x =>
      match x with
      | Except.ok a => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k)
      | Except.error e => Fitree.ret (Except.error e)) =
    fun x =>
    Fitree.bind
      (match x with
      | Except.ok a => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)
      | Except.error e => Fitree.ret (Except.error e))
      fun x =>
      match x with
      | Except.error e => Fitree.ret (Except.error e)
      | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)

State before:
case Vis.a
T : Type
E : Type → Type
R : Type
k : T → Fitree (UBE +' E) R
T✝ : Type
e✝ : sum1 UBE E T✝
k✝ : T✝ → Fitree (UBE +' E) T
ih :
  ∀ (a : T✝),
    Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k) =
      Fitree.bind (Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)) fun x =>
        match x with
        | Except.error ε => Fitree.ret (Except.error ε)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
fequal2 : ∀ (α β : Type 1) (f g : α → β) (x y : α), f = g → x = y → f x = g y
⊢ Fitree.bind (Fitree.case UBE.handle Fitree.liftHandler T✝ e✝) =
    Fitree.bind (Fitree.case UBE.handle Fitree.liftHandler T✝ e✝)

case Vis.a
T : Type
E : Type → Type
R : Type
k : T → Fitree (UBE +' E) R
T✝ : Type
e✝ : sum1 UBE E T✝
k✝ : T✝ → Fitree (UBE +' E) T
ih :
  ∀ (a : T✝),
    Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k) =
      Fitree.bind (Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)) fun x =>
        match x with
        | Except.error ε => Fitree.ret (Except.error ε)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
fequal2 : ∀ (α β : Type 1) (f g : α → β) (x y : α), f = g → x = y → f x = g y
⊢ (fun x =>
      match x with
      | Except.ok a => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k)
      | Except.error e => Fitree.ret (Except.error e)) =
    fun x =>
    Fitree.bind
      (match x with
      | Except.ok a => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)
      | Except.error e => Fitree.ret (Except.error e))
      fun x =>
      match x with
      | Except.error e => Fitree.ret (Except.error e)
      | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
Tactic:
rfl
State after:
case Vis.a
T : Type
E : Type → Type
R : Type
k : T → Fitree (UBE +' E) R
T✝ : Type
e✝ : sum1 UBE E T✝
k✝ : T✝ → Fitree (UBE +' E) T
ih :
  ∀ (a : T✝),
    Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k) =
      Fitree.bind (Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)) fun x =>
        match x with
        | Except.error ε => Fitree.ret (Except.error ε)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
fequal2 : ∀ (α β : Type 1) (f g : α → β) (x y : α), f = g → x = y → f x = g y
⊢ (fun x =>
      match x with
      | Except.ok a => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k)
      | Except.error e => Fitree.ret (Except.error e)) =
    fun x =>
    Fitree.bind
      (match x with
      | Except.ok a => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)
      | Except.error e => Fitree.ret (Except.error e))
      fun x =>
      match x with
      | Except.error e => Fitree.ret (Except.error e)
      | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)

State before:
case Vis.a
T : Type
E : Type → Type
R : Type
k : T → Fitree (UBE +' E) R
T✝ : Type
e✝ : sum1 UBE E T✝
k✝ : T✝ → Fitree (UBE +' E) T
ih :
  ∀ (a : T✝),
    Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k) =
      Fitree.bind (Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)) fun x =>
        match x with
        | Except.error ε => Fitree.ret (Except.error ε)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
fequal2 : ∀ (α β : Type 1) (f g : α → β) (x y : α), f = g → x = y → f x = g y
⊢ (fun x =>
      match x with
      | Except.ok a => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k)
      | Except.error e => Fitree.ret (Except.error e)) =
    fun x =>
    Fitree.bind
      (match x with
      | Except.ok a => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)
      | Except.error e => Fitree.ret (Except.error e))
      fun x =>
      match x with
      | Except.error e => Fitree.ret (Except.error e)
      | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
Tactic:
funext x
State after:
case Vis.a.h
T : Type
E : Type → Type
R : Type
k : T → Fitree (UBE +' E) R
T✝ : Type
e✝ : sum1 UBE E T✝
k✝ : T✝ → Fitree (UBE +' E) T
ih :
  ∀ (a : T✝),
    Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k) =
      Fitree.bind (Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)) fun x =>
        match x with
        | Except.error ε => Fitree.ret (Except.error ε)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
fequal2 : ∀ (α β : Type 1) (f g : α → β) (x y : α), f = g → x = y → f x = g y
x : Except String T✝
⊢ (match x with
    | Except.ok a => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k)
    | Except.error e => Fitree.ret (Except.error e)) =
    Fitree.bind
      (match x with
      | Except.ok a => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)
      | Except.error e => Fitree.ret (Except.error e))
      fun x =>
      match x with
      | Except.error e => Fitree.ret (Except.error e)
      | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)

State before:
case Vis.a.h
T : Type
E : Type → Type
R : Type
k : T → Fitree (UBE +' E) R
T✝ : Type
e✝ : sum1 UBE E T✝
k✝ : T✝ → Fitree (UBE +' E) T
ih :
  ∀ (a : T✝),
    Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k) =
      Fitree.bind (Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)) fun x =>
        match x with
        | Except.error ε => Fitree.ret (Except.error ε)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
fequal2 : ∀ (α β : Type 1) (f g : α → β) (x y : α), f = g → x = y → f x = g y
x : Except String T✝
⊢ (match x with
    | Except.ok a => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k)
    | Except.error e => Fitree.ret (Except.error e)) =
    Fitree.bind
      (match x with
      | Except.ok a => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)
      | Except.error e => Fitree.ret (Except.error e))
      fun x =>
      match x with
      | Except.error e => Fitree.ret (Except.error e)
      | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
Tactic:
cases x <;> simp [ih]
State after:
no goals

State before:
T : Type
E : Type → Type
R : Type
k : T → Fitree (UBE +' E) R
T✝ : Type
e✝ : sum1 UBE E T✝
k✝ : T✝ → Fitree (UBE +' E) T
ih :
  ∀ (a : T✝),
    Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (Fitree.bind (k✝ a) k) =
      Fitree.bind (Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k✝ a)) fun x =>
        match x with
        | Except.error ε => Fitree.ret (Except.error ε)
        | Except.ok x => Fitree.interp (Fitree.case UBE.handle Fitree.liftHandler) (k x)
α : Sort ?u.10648
β : Sort ?u.10649
f g : α → β
x y : α
h₁ : f = g
h₂ : x = y
⊢ f x = g y
Tactic:
simp [h₁, h₂]
State after:
no goals