-- Mathlib/Computability/PostTuringMachine.lean
theorem tr_respects : Respects (TM0.step M) (TM1.step (tr M)) fun a b ↦ trCfg M a = b :=
  fun_respects.2 fun ⟨q, T⟩ ↦ by
    rcases e : M q T.1 with - | val
    · simp only [TM0.step, trCfg, e]; exact Eq.refl none
    obtain ⟨q', s⟩ := val
    simp only [FRespects, TM0.step, trCfg, e, Option.isSome, cond, Option.map_some']
    revert e
    have : TM1.step (tr M) ⟨some (Λ'.act s q'), (), T⟩ = some ⟨some (Λ'.normal q'), (), match s with
        | TM0.Stmt.move d => T.move d
        | TM0.Stmt.write a => T.write a⟩

Proof state:
case some.mk.refine_2.none.hab
Γ : Type u_1
inst✝¹ : Inhabited Γ
Λ : Type u_2
inst✝ : Inhabited Λ
M : TM0.Machine Γ Λ
x✝ : TM0.Cfg Γ Λ
q : Λ
T : Tape Γ
q' : Λ
s : TM0.Stmt Γ
this :
  TM1.step (tr M) { l := some (Λ'.act s q'), var := (), Tape := T } =
    some
      { l := some (Λ'.normal q'), var := (),
        Tape :=
          match s with
          | TM0.Stmt.move d => Tape.move d T
          | TM0.Stmt.write a => Tape.write a T }
e : M q T.head = some (q', s)
e' :
  M q'
      (match s with
        | TM0.Stmt.move d => Tape.move d T
        | TM0.Stmt.write a => Tape.write a T).head =
    none
⊢ { l := none, var := (),
      Tape :=
        match s with
        | TM0.Stmt.move d => Tape.move d T
        | TM0.Stmt.write a => Tape.write a T } ∈
    some
      (bif none.isNone then
        { l := none, var := (),
          Tape :=
            match s with
            | TM0.Stmt.move d => Tape.move d T
            | TM0.Stmt.write a => Tape.write a T }
      else
        {
          l :=
            some
              (match none with
              | none => default
              | some (q', s) => Λ'.act s q'),
          var := (),
          Tape :=
            match s with
            | TM0.Stmt.move d => Tape.move d T
            | TM0.Stmt.write a => Tape.write a T })

Tactic:
rfl

Result:
no goals

Proof state:
Γ : Type u_1
inst✝¹ : Inhabited Γ
Λ : Type u_2
inst✝ : Inhabited Λ
M : TM0.Machine Γ Λ
x✝ : TM0.Cfg Γ Λ
q : Λ
T : Tape Γ
⊢ FRespects (TM1.step (tr M)) (trCfg M) (trCfg M { q := q, Tape := T }) (TM0.step M { q := q, Tape := T })

Tactic:
rcases e : M q T.1 with - | val

Result:
case none
Γ : Type u_1
inst✝¹ : Inhabited Γ
Λ : Type u_2
inst✝ : Inhabited Λ
M : TM0.Machine Γ Λ
x✝ : TM0.Cfg Γ Λ
q : Λ
T : Tape Γ
e : M q T.head = none
⊢ FRespects (TM1.step (tr M)) (trCfg M) (trCfg M { q := q, Tape := T }) (TM0.step M { q := q, Tape := T })

case some
Γ : Type u_1
inst✝¹ : Inhabited Γ
Λ : Type u_2
inst✝ : Inhabited Λ
M : TM0.Machine Γ Λ
x✝ : TM0.Cfg Γ Λ
q : Λ
T : Tape Γ
val : Λ × TM0.Stmt Γ
e : M q T.head = some val
⊢ FRespects (TM1.step (tr M)) (trCfg M) (trCfg M { q := q, Tape := T }) (TM0.step M { q := q, Tape := T })

Proof state:
case none
Γ : Type u_1
inst✝¹ : Inhabited Γ
Λ : Type u_2
inst✝ : Inhabited Λ
M : TM0.Machine Γ Λ
x✝ : TM0.Cfg Γ Λ
q : Λ
T : Tape Γ
e : M q T.head = none
⊢ FRespects (TM1.step (tr M)) (trCfg M) (trCfg M { q := q, Tape := T }) (TM0.step M { q := q, Tape := T })

Tactic:
simp only [TM0.step, trCfg, e]

Result:
case none
Γ : Type u_1
inst✝¹ : Inhabited Γ
Λ : Type u_2
inst✝ : Inhabited Λ
M : TM0.Machine Γ Λ
x✝ : TM0.Cfg Γ Λ
q : Λ
T : Tape Γ
e : M q T.head = none
⊢ FRespects (TM1.step (tr M)) (trCfg M) { l := bif none.isSome then some (Λ'.normal q) else none, var := (), Tape := T }
    (Option.map
      (fun x =>
        { q := x.1,
          Tape :=
            match x.2 with
            | TM0.Stmt.move d => Tape.move d T
            | TM0.Stmt.write a => Tape.write a T })
      none)

Proof state:
case some.mk.refine_1
Γ : Type u_1
inst✝¹ : Inhabited Γ
Λ : Type u_2
inst✝ : Inhabited Λ
M : TM0.Machine Γ Λ
x✝ : TM0.Cfg Γ Λ
q : Λ
T : Tape Γ
q' : Λ
s : TM0.Stmt Γ
this :
  TM1.step (tr M) { l := some (Λ'.act s q'), var := (), Tape := T } =
    some
      { l := some (Λ'.normal q'), var := (),
        Tape :=
          match s with
          | TM0.Stmt.move d => Tape.move d T
          | TM0.Stmt.write a => Tape.write a T }
e : M q T.head = some (q', s)
⊢ { l := some (Λ'.act s q'), var := (), Tape := T } ∈
    some
      (bif (M q T.head).isNone then { l := none, var := (), Tape := T }
      else
        {
          l :=
            some
              (match M q T.head with
              | none => default
              | some (q', s) => Λ'.act s q'),
          var := (), Tape := T })

Tactic:
rw [e]

Result:
case some.mk.refine_1
Γ : Type u_1
inst✝¹ : Inhabited Γ
Λ : Type u_2
inst✝ : Inhabited Λ
M : TM0.Machine Γ Λ
x✝ : TM0.Cfg Γ Λ
q : Λ
T : Tape Γ
q' : Λ
s : TM0.Stmt Γ
this :
  TM1.step (tr M) { l := some (Λ'.act s q'), var := (), Tape := T } =
    some
      { l := some (Λ'.normal q'), var := (),
        Tape :=
          match s with
          | TM0.Stmt.move d => Tape.move d T
          | TM0.Stmt.write a => Tape.write a T }
e : M q T.head = some (q', s)
⊢ { l := some (Λ'.act s q'), var := (), Tape := T } ∈
    some
      (bif (some (q', s)).isNone then { l := none, var := (), Tape := T }
      else
        {
          l :=
            some
              (match some (q', s) with
              | none => default
              | some (q', s) => Λ'.act s q'),
          var := (), Tape := T })

Proof state:
case some.mk.refine_1
Γ : Type u_1
inst✝¹ : Inhabited Γ
Λ : Type u_2
inst✝ : Inhabited Λ
M : TM0.Machine Γ Λ
x✝ : TM0.Cfg Γ Λ
q : Λ
T : Tape Γ
q' : Λ
s : TM0.Stmt Γ
this :
  TM1.step (tr M) { l := some (Λ'.act s q'), var := (), Tape := T } =
    some
      { l := some (Λ'.normal q'), var := (),
        Tape :=
          match s with
          | TM0.Stmt.move d => Tape.move d T
          | TM0.Stmt.write a => Tape.write a T }
e : M q T.head = some (q', s)
⊢ { l := some (Λ'.act s q'), var := (), Tape := T } ∈ TM1.step (tr M) { l := some (Λ'.normal q), var := (), Tape := T }

Tactic:
simp only [TM1.step, TM1.stepAux, tr]

Result:
case some.mk.refine_1
Γ : Type u_1
inst✝¹ : Inhabited Γ
Λ : Type u_2
inst✝ : Inhabited Λ
M : TM0.Machine Γ Λ
x✝ : TM0.Cfg Γ Λ
q : Λ
T : Tape Γ
q' : Λ
s : TM0.Stmt Γ
this :
  TM1.step (tr M) { l := some (Λ'.act s q'), var := (), Tape := T } =
    some
      { l := some (Λ'.normal q'), var := (),
        Tape :=
          match s with
          | TM0.Stmt.move d => Tape.move d T
          | TM0.Stmt.write a => Tape.write a T }
e : M q T.head = some (q', s)
⊢ { l := some (Λ'.act s q'), var := (), Tape := T } ∈
    some
      (bif (M q T.head).isNone then { l := none, var := (), Tape := T }
      else
        {
          l :=
            some
              (match M q T.head with
              | none => default
              | some (q', s) => Λ'.act s q'),
          var := (), Tape := T })