l3lab/ntp-mathlib huggingface dataset:
theorem tail_congr {s t : WSeq α} (h : s ~ʷ t) : tail s ~ʷ tail t := by
  apply flatten_congr
  dsimp only [(· <$> ·)]; rw [← Computation.bind_pure, ← Computation.bind_pure]
  apply liftRel_bind _ _ (destruct_congr h)
  -- Porting note: These 2 theorems should be excluded.
  intro a b h; simp [-liftRel_pure_left, -liftRel_pure_right]
  cases' a with a <;> cases' b with b
  · trivial
  · cases h
  · 

Proof state:
case a.some.none
α : Type u
β : Type v
γ : Type w
s t : WSeq α
h✝ : s ~ʷ t
a : α × WSeq α
h : BisimO (fun x x_1 => x ~ʷ x_1) (some a) none
⊢ Option.rec nil Prod.snd (some a) ~ʷ Option.rec nil Prod.snd none

Next tactic:
cases a
theorem tail_congr {s t : WSeq α} (h : s ~ʷ t) : tail s ~ʷ tail t := by
  apply flatten_congr
  dsimp only [(· <$> ·)]; rw [← Computation.bind_pure, ← Computation.bind_pure]
  apply liftRel_bind _ _ (destruct_congr h)
  -- Porting note: These 2 theorems should be excluded.
  intro a b h; simp [-liftRel_pure_left, -liftRel_pure_right]
  cases' a with a <;> cases' b with b
  · trivial
  · cases h
  · cases a
    

Proof state:
case a.some.none.mk
α : Type u
β : Type v
γ : Type w
s t : WSeq α
h✝ : s ~ʷ t
fst✝ : α
snd✝ : WSeq α
h : BisimO (fun x x_1 => x ~ʷ x_1) (some (fst✝, snd✝)) none
⊢ Option.rec nil Prod.snd (some (fst✝, snd✝)) ~ʷ Option.rec nil Prod.snd none

Next tactic:
cases h
theorem tail_congr {s t : WSeq α} (h : s ~ʷ t) : tail s ~ʷ tail t := by
  apply flatten_congr
  dsimp only [(· <$> ·)]; rw [← Computation.bind_pure, ← Computation.bind_pure]
  apply liftRel_bind _ _ (destruct_congr h)
  -- Porting note: These 2 theorems should be excluded.
  intro a b h; simp [-liftRel_pure_left, -liftRel_pure_right]
  cases' a with a <;> cases' b with b
  · trivial
  · cases h
  · cases a
    cases h
  · 

Proof state:
case a.some.some
α : Type u
β : Type v
γ : Type w
s t : WSeq α
h✝ : s ~ʷ t
a b : α × WSeq α
h : BisimO (fun x x_1 => x ~ʷ x_1) (some a) (some b)
⊢ Option.rec nil Prod.snd (some a) ~ʷ Option.rec nil Prod.snd (some b)

Next tactic:
cases' a with a s'
theorem tail_congr {s t : WSeq α} (h : s ~ʷ t) : tail s ~ʷ tail t := by
  apply flatten_congr
  dsimp only [(· <$> ·)]; rw [← Computation.bind_pure, ← Computation.bind_pure]
  apply liftRel_bind _ _ (destruct_congr h)
  -- Porting note: These 2 theorems should be excluded.
  intro a b h; simp [-liftRel_pure_left, -liftRel_pure_right]
  cases' a with a <;> cases' b with b
  · trivial
  · cases h
  · cases a
    cases h
  · cases' a with a s'
    

Proof state:
case a.some.some.mk
α : Type u
β : Type v
γ : Type w
s t : WSeq α
h✝ : s ~ʷ t
b : α × WSeq α
a : α
s' : WSeq α
h : BisimO (fun x x_1 => x ~ʷ x_1) (some (a, s')) (some b)
⊢ Option.rec nil Prod.snd (some (a, s')) ~ʷ Option.rec nil Prod.snd (some b)

Next tactic:
cases' b with b t'
theorem tail_congr {s t : WSeq α} (h : s ~ʷ t) : tail s ~ʷ tail t := by
  apply flatten_congr
  dsimp only [(· <$> ·)]; rw [← Computation.bind_pure, ← Computation.bind_pure]
  apply liftRel_bind _ _ (destruct_congr h)
  -- Porting note: These 2 theorems should be excluded.
  intro a b h; simp [-liftRel_pure_left, -liftRel_pure_right]
  cases' a with a <;> cases' b with b
  · trivial
  · cases h
  · cases a
    cases h
  · cases' a with a s'
    cases' b with b t'
    

Proof state:
case a.some.some.mk.mk
α : Type u
β : Type v
γ : Type w
s t : WSeq α
h✝ : s ~ʷ t
a : α
s' : WSeq α
b : α
t' : WSeq α
h : BisimO (fun x x_1 => x ~ʷ x_1) (some (a, s')) (some (b, t'))
⊢ Option.rec nil Prod.snd (some (a, s')) ~ʷ Option.rec nil Prod.snd (some (b, t'))

Next tactic:
exact h.right
theorem dropn_congr {s t : WSeq α} (h : s ~ʷ t) (n) : drop s n ~ʷ drop t n := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
s t : WSeq α
h : s ~ʷ t
n : ℕ
⊢ drop s n ~ʷ drop t n

Next tactic:
induction n
theorem dropn_congr {s t : WSeq α} (h : s ~ʷ t) (n) : drop s n ~ʷ drop t n := by
  induction n <;> 

Proof state:
case zero
α : Type u
β : Type v
γ : Type w
s t : WSeq α
h : s ~ʷ t
⊢ drop s Nat.zero ~ʷ drop t Nat.zero

Next tactic:
simp [*, tail_congr, drop]
theorem dropn_congr {s t : WSeq α} (h : s ~ʷ t) (n) : drop s n ~ʷ drop t n := by
  induction n <;> 

Proof state:
case succ
α : Type u
β : Type v
γ : Type w
s t : WSeq α
h : s ~ʷ t
n✝ : ℕ
n_ih✝ : drop s n✝ ~ʷ drop t n✝
⊢ drop s (Nat.succ n✝) ~ʷ drop t (Nat.succ n✝)

Next tactic:
simp [*, tail_congr, drop]
theorem productive_congr {s t : WSeq α} (h : s ~ʷ t) : Productive s ↔ Productive t := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
s t : WSeq α
h : s ~ʷ t
⊢ Productive s ↔ Productive t

Next tactic:
simp only [productive_iff]
theorem productive_congr {s t : WSeq α} (h : s ~ʷ t) : Productive s ↔ Productive t := by
  simp only [productive_iff]; 

Proof state:
α : Type u
β : Type v
γ : Type w
s t : WSeq α
h : s ~ʷ t
⊢ (∀ (n : ℕ), Terminates (get? s n)) ↔ ∀ (n : ℕ), Terminates (get? t n)

Next tactic:
exact forall_congr' fun n => terminates_congr <| get?_congr h _
theorem Equiv.ext {s t : WSeq α} (h : ∀ n, get? s n ~ get? t n) : s ~ʷ t :=
  ⟨fun s t => ∀ n, get? s n ~ get? t n, h, fun {s t} h => by
    

Proof state:
α : Type u
β : Type v
γ : Type w
s✝ t✝ : WSeq α
h✝ : ∀ (n : ℕ), get? s✝ n ~ get? t✝ n
s t : WSeq α
h : (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) s t
⊢ Computation.LiftRel (LiftRelO (fun x x_1 => x = x_1) fun s t => ∀ (n : ℕ), get? s n ~ get? t n) (destruct s)
    (destruct t)

Next tactic:
refine' liftRel_def.2 ⟨_, _⟩
theorem Equiv.ext {s t : WSeq α} (h : ∀ n, get? s n ~ get? t n) : s ~ʷ t :=
  ⟨fun s t => ∀ n, get? s n ~ get? t n, h, fun {s t} h => by
    refine' liftRel_def.2 ⟨_, _⟩
    · 

Proof state:
case refine'_1
α : Type u
β : Type v
γ : Type w
s✝ t✝ : WSeq α
h✝ : ∀ (n : ℕ), get? s✝ n ~ get? t✝ n
s t : WSeq α
h : (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) s t
⊢ Terminates (destruct s) ↔ Terminates (destruct t)

Next tactic:
rw [← head_terminates_iff, ← head_terminates_iff]
theorem Equiv.ext {s t : WSeq α} (h : ∀ n, get? s n ~ get? t n) : s ~ʷ t :=
  ⟨fun s t => ∀ n, get? s n ~ get? t n, h, fun {s t} h => by
    refine' liftRel_def.2 ⟨_, _⟩
    · rw [← head_terminates_iff, ← head_terminates_iff]
      

Proof state:
case refine'_1
α : Type u
β : Type v
γ : Type w
s✝ t✝ : WSeq α
h✝ : ∀ (n : ℕ), get? s✝ n ~ get? t✝ n
s t : WSeq α
h : (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) s t
⊢ Terminates (head s) ↔ Terminates (head t)

Next tactic:
exact terminates_congr (h 0)
theorem Equiv.ext {s t : WSeq α} (h : ∀ n, get? s n ~ get? t n) : s ~ʷ t :=
  ⟨fun s t => ∀ n, get? s n ~ get? t n, h, fun {s t} h => by
    refine' liftRel_def.2 ⟨_, _⟩
    · rw [← head_terminates_iff, ← head_terminates_iff]
      exact terminates_congr (h 0)
    · 

Proof state:
case refine'_2
α : Type u
β : Type v
γ : Type w
s✝ t✝ : WSeq α
h✝ : ∀ (n : ℕ), get? s✝ n ~ get? t✝ n
s t : WSeq α
h : (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) s t
⊢ ∀ {a b : Option (α × WSeq α)},
    a ∈ destruct s → b ∈ destruct t → LiftRelO (fun x x_1 => x = x_1) (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) a b

Next tactic:
intro a b ma mb
theorem Equiv.ext {s t : WSeq α} (h : ∀ n, get? s n ~ get? t n) : s ~ʷ t :=
  ⟨fun s t => ∀ n, get? s n ~ get? t n, h, fun {s t} h => by
    refine' liftRel_def.2 ⟨_, _⟩
    · rw [← head_terminates_iff, ← head_terminates_iff]
      exact terminates_congr (h 0)
    · intro a b ma mb
      

Proof state:
case refine'_2
α : Type u
β : Type v
γ : Type w
s✝ t✝ : WSeq α
h✝ : ∀ (n : ℕ), get? s✝ n ~ get? t✝ n
s t : WSeq α
h : (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) s t
a b : Option (α × WSeq α)
ma : a ∈ destruct s
mb : b ∈ destruct t
⊢ LiftRelO (fun x x_1 => x = x_1) (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) a b

Next tactic:
cases' a with a
theorem Equiv.ext {s t : WSeq α} (h : ∀ n, get? s n ~ get? t n) : s ~ʷ t :=
  ⟨fun s t => ∀ n, get? s n ~ get? t n, h, fun {s t} h => by
    refine' liftRel_def.2 ⟨_, _⟩
    · rw [← head_terminates_iff, ← head_terminates_iff]
      exact terminates_congr (h 0)
    · intro a b ma mb
      cases' a with a <;> 

Proof state:
case refine'_2.none
α : Type u
β : Type v
γ : Type w
s✝ t✝ : WSeq α
h✝ : ∀ (n : ℕ), get? s✝ n ~ get? t✝ n
s t : WSeq α
h : (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) s t
b : Option (α × WSeq α)
mb : b ∈ destruct t
ma : none ∈ destruct s
⊢ LiftRelO (fun x x_1 => x = x_1) (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) none b

Next tactic:
cases' b with b
theorem Equiv.ext {s t : WSeq α} (h : ∀ n, get? s n ~ get? t n) : s ~ʷ t :=
  ⟨fun s t => ∀ n, get? s n ~ get? t n, h, fun {s t} h => by
    refine' liftRel_def.2 ⟨_, _⟩
    · rw [← head_terminates_iff, ← head_terminates_iff]
      exact terminates_congr (h 0)
    · intro a b ma mb
      cases' a with a <;> 

Proof state:
case refine'_2.some
α : Type u
β : Type v
γ : Type w
s✝ t✝ : WSeq α
h✝ : ∀ (n : ℕ), get? s✝ n ~ get? t✝ n
s t : WSeq α
h : (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) s t
b : Option (α × WSeq α)
mb : b ∈ destruct t
a : α × WSeq α
ma : some a ∈ destruct s
⊢ LiftRelO (fun x x_1 => x = x_1) (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) (some a) b

Next tactic:
cases' b with b
theorem Equiv.ext {s t : WSeq α} (h : ∀ n, get? s n ~ get? t n) : s ~ʷ t :=
  ⟨fun s t => ∀ n, get? s n ~ get? t n, h, fun {s t} h => by
    refine' liftRel_def.2 ⟨_, _⟩
    · rw [← head_terminates_iff, ← head_terminates_iff]
      exact terminates_congr (h 0)
    · intro a b ma mb
      cases' a with a <;> cases' b with b
      · 

Proof state:
case refine'_2.none.none
α : Type u
β : Type v
γ : Type w
s✝ t✝ : WSeq α
h✝ : ∀ (n : ℕ), get? s✝ n ~ get? t✝ n
s t : WSeq α
h : (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) s t
ma : none ∈ destruct s
mb : none ∈ destruct t
⊢ LiftRelO (fun x x_1 => x = x_1) (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) none none

Next tactic:
trivial
theorem Equiv.ext {s t : WSeq α} (h : ∀ n, get? s n ~ get? t n) : s ~ʷ t :=
  ⟨fun s t => ∀ n, get? s n ~ get? t n, h, fun {s t} h => by
    refine' liftRel_def.2 ⟨_, _⟩
    · rw [← head_terminates_iff, ← head_terminates_iff]
      exact terminates_congr (h 0)
    · intro a b ma mb
      cases' a with a <;> cases' b with b
      · trivial
      · 

Proof state:
case refine'_2.none.some
α : Type u
β : Type v
γ : Type w
s✝ t✝ : WSeq α
h✝ : ∀ (n : ℕ), get? s✝ n ~ get? t✝ n
s t : WSeq α
h : (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) s t
ma : none ∈ destruct s
b : α × WSeq α
mb : some b ∈ destruct t
⊢ LiftRelO (fun x x_1 => x = x_1) (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) none (some b)

Next tactic:
injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb))
theorem Equiv.ext {s t : WSeq α} (h : ∀ n, get? s n ~ get? t n) : s ~ʷ t :=
  ⟨fun s t => ∀ n, get? s n ~ get? t n, h, fun {s t} h => by
    refine' liftRel_def.2 ⟨_, _⟩
    · rw [← head_terminates_iff, ← head_terminates_iff]
      exact terminates_congr (h 0)
    · intro a b ma mb
      cases' a with a <;> cases' b with b
      · trivial
      · injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb))
      · 

Proof state:
case refine'_2.some.none
α : Type u
β : Type v
γ : Type w
s✝ t✝ : WSeq α
h✝ : ∀ (n : ℕ), get? s✝ n ~ get? t✝ n
s t : WSeq α
h : (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) s t
a : α × WSeq α
ma : some a ∈ destruct s
mb : none ∈ destruct t
⊢ LiftRelO (fun x x_1 => x = x_1) (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) (some a) none

Next tactic:
injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb))
theorem Equiv.ext {s t : WSeq α} (h : ∀ n, get? s n ~ get? t n) : s ~ʷ t :=
  ⟨fun s t => ∀ n, get? s n ~ get? t n, h, fun {s t} h => by
    refine' liftRel_def.2 ⟨_, _⟩
    · rw [← head_terminates_iff, ← head_terminates_iff]
      exact terminates_congr (h 0)
    · intro a b ma mb
      cases' a with a <;> cases' b with b
      · trivial
      · injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb))
      · injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb))
      · 

Proof state:
case refine'_2.some.some
α : Type u
β : Type v
γ : Type w
s✝ t✝ : WSeq α
h✝ : ∀ (n : ℕ), get? s✝ n ~ get? t✝ n
s t : WSeq α
h : (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) s t
a : α × WSeq α
ma : some a ∈ destruct s
b : α × WSeq α
mb : some b ∈ destruct t
⊢ LiftRelO (fun x x_1 => x = x_1) (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) (some a) (some b)

Next tactic:
cases' a with a s'
theorem Equiv.ext {s t : WSeq α} (h : ∀ n, get? s n ~ get? t n) : s ~ʷ t :=
  ⟨fun s t => ∀ n, get? s n ~ get? t n, h, fun {s t} h => by
    refine' liftRel_def.2 ⟨_, _⟩
    · rw [← head_terminates_iff, ← head_terminates_iff]
      exact terminates_congr (h 0)
    · intro a b ma mb
      cases' a with a <;> cases' b with b
      · trivial
      · injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb))
      · injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb))
      · cases' a with a s'
        

Proof state:
case refine'_2.some.some.mk
α : Type u
β : Type v
γ : Type w
s✝ t✝ : WSeq α
h✝ : ∀ (n : ℕ), get? s✝ n ~ get? t✝ n
s t : WSeq α
h : (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) s t
b : α × WSeq α
mb : some b ∈ destruct t
a : α
s' : WSeq α
ma : some (a, s') ∈ destruct s
⊢ LiftRelO (fun x x_1 => x = x_1) (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) (some (a, s')) (some b)

Next tactic:
cases' b with b t'
theorem Equiv.ext {s t : WSeq α} (h : ∀ n, get? s n ~ get? t n) : s ~ʷ t :=
  ⟨fun s t => ∀ n, get? s n ~ get? t n, h, fun {s t} h => by
    refine' liftRel_def.2 ⟨_, _⟩
    · rw [← head_terminates_iff, ← head_terminates_iff]
      exact terminates_congr (h 0)
    · intro a b ma mb
      cases' a with a <;> cases' b with b
      · trivial
      · injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb))
      · injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb))
      · cases' a with a s'
        cases' b with b t'
        

Proof state:
case refine'_2.some.some.mk.mk
α : Type u
β : Type v
γ : Type w
s✝ t✝ : WSeq α
h✝ : ∀ (n : ℕ), get? s✝ n ~ get? t✝ n
s t : WSeq α
h : (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) s t
a : α
s' : WSeq α
ma : some (a, s') ∈ destruct s
b : α
t' : WSeq α
mb : some (b, t') ∈ destruct t
⊢ LiftRelO (fun x x_1 => x = x_1) (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) (some (a, s')) (some (b, t'))

Next tactic:
injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb)) with
          ab
theorem Equiv.ext {s t : WSeq α} (h : ∀ n, get? s n ~ get? t n) : s ~ʷ t :=
  ⟨fun s t => ∀ n, get? s n ~ get? t n, h, fun {s t} h => by
    refine' liftRel_def.2 ⟨_, _⟩
    · rw [← head_terminates_iff, ← head_terminates_iff]
      exact terminates_congr (h 0)
    · intro a b ma mb
      cases' a with a <;> cases' b with b
      · trivial
      · injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb))
      · injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb))
      · cases' a with a s'
        cases' b with b t'
        injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb)) with
          ab
        

Proof state:
case refine'_2.some.some.mk.mk
α : Type u
β : Type v
γ : Type w
s✝ t✝ : WSeq α
h✝ : ∀ (n : ℕ), get? s✝ n ~ get? t✝ n
s t : WSeq α
h : (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) s t
a : α
s' : WSeq α
ma : some (a, s') ∈ destruct s
b : α
t' : WSeq α
mb : some (b, t') ∈ destruct t
ab : (a, s').1 = (b, t').1
⊢ LiftRelO (fun x x_1 => x = x_1) (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) (some (a, s')) (some (b, t'))

Next tactic:
refine' ⟨ab, fun n => _⟩
theorem Equiv.ext {s t : WSeq α} (h : ∀ n, get? s n ~ get? t n) : s ~ʷ t :=
  ⟨fun s t => ∀ n, get? s n ~ get? t n, h, fun {s t} h => by
    refine' liftRel_def.2 ⟨_, _⟩
    · rw [← head_terminates_iff, ← head_terminates_iff]
      exact terminates_congr (h 0)
    · intro a b ma mb
      cases' a with a <;> cases' b with b
      · trivial
      · injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb))
      · injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb))
      · cases' a with a s'
        cases' b with b t'
        injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb)) with
          ab
        refine' ⟨ab, fun n => _⟩
        

Proof state:
case refine'_2.some.some.mk.mk
α : Type u
β : Type v
γ : Type w
s✝ t✝ : WSeq α
h✝ : ∀ (n : ℕ), get? s✝ n ~ get? t✝ n
s t : WSeq α
h : (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) s t
a : α
s' : WSeq α
ma : some (a, s') ∈ destruct s
b : α
t' : WSeq α
mb : some (b, t') ∈ destruct t
ab : (a, s').1 = (b, t').1
n : ℕ
⊢ get? s' n ~ get? t' n

Next tactic:
refine'
          (get?_congr (flatten_equiv (Computation.mem_map _ ma)) n).symm.trans
            ((_ : get? (tail s) n ~ get? (tail t) n).trans
              (get?_congr (flatten_equiv (Computation.mem_map _ mb)) n))
theorem Equiv.ext {s t : WSeq α} (h : ∀ n, get? s n ~ get? t n) : s ~ʷ t :=
  ⟨fun s t => ∀ n, get? s n ~ get? t n, h, fun {s t} h => by
    refine' liftRel_def.2 ⟨_, _⟩
    · rw [← head_terminates_iff, ← head_terminates_iff]
      exact terminates_congr (h 0)
    · intro a b ma mb
      cases' a with a <;> cases' b with b
      · trivial
      · injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb))
      · injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb))
      · cases' a with a s'
        cases' b with b t'
        injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb)) with
          ab
        refine' ⟨ab, fun n => _⟩
        refine'
          (get?_congr (flatten_equiv (Computation.mem_map _ ma)) n).symm.trans
            ((_ : get? (tail s) n ~ get? (tail t) n).trans
              (get?_congr (flatten_equiv (Computation.mem_map _ mb)) n))
        

Proof state:
case refine'_2.some.some.mk.mk
α : Type u
β : Type v
γ : Type w
s✝ t✝ : WSeq α
h✝ : ∀ (n : ℕ), get? s✝ n ~ get? t✝ n
s t : WSeq α
h : (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) s t
a : α
s' : WSeq α
ma : some (a, s') ∈ destruct s
b : α
t' : WSeq α
mb : some (b, t') ∈ destruct t
ab : (a, s').1 = (b, t').1
n : ℕ
⊢ get? (tail s) n ~ get? (tail t) n

Next tactic:
rw [get?_tail, get?_tail]
theorem Equiv.ext {s t : WSeq α} (h : ∀ n, get? s n ~ get? t n) : s ~ʷ t :=
  ⟨fun s t => ∀ n, get? s n ~ get? t n, h, fun {s t} h => by
    refine' liftRel_def.2 ⟨_, _⟩
    · rw [← head_terminates_iff, ← head_terminates_iff]
      exact terminates_congr (h 0)
    · intro a b ma mb
      cases' a with a <;> cases' b with b
      · trivial
      · injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb))
      · injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb))
      · cases' a with a s'
        cases' b with b t'
        injection mem_unique (Computation.mem_map _ ma) ((h 0 _).2 (Computation.mem_map _ mb)) with
          ab
        refine' ⟨ab, fun n => _⟩
        refine'
          (get?_congr (flatten_equiv (Computation.mem_map _ ma)) n).symm.trans
            ((_ : get? (tail s) n ~ get? (tail t) n).trans
              (get?_congr (flatten_equiv (Computation.mem_map _ mb)) n))
        rw [get?_tail, get?_tail]
        

Proof state:
case refine'_2.some.some.mk.mk
α : Type u
β : Type v
γ : Type w
s✝ t✝ : WSeq α
h✝ : ∀ (n : ℕ), get? s✝ n ~ get? t✝ n
s t : WSeq α
h : (fun s t => ∀ (n : ℕ), get? s n ~ get? t n) s t
a : α
s' : WSeq α
ma : some (a, s') ∈ destruct s
b : α
t' : WSeq α
mb : some (b, t') ∈ destruct t
ab : (a, s').1 = (b, t').1
n : ℕ
⊢ get? s (n + 1) ~ get? t (n + 1)

Next tactic:
apply h
theorem length_eq_map (s : WSeq α) : length s = Computation.map List.length (toList s) := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
⊢ length s = Computation.map List.length (toList s)

Next tactic:
refine'
    Computation.eq_of_bisim
      (fun c1 c2 =>
        ∃ (l : List α) (s : WSeq α),
          c1 = Computation.corec (fun ⟨n, s⟩ =>
            match Seq.destruct s with
            | none => Sum.inl n
            | some (none, s') => Sum.inr (n, s')
            | some (some _, s') => Sum.inr (n + 1, s')) (l.length, s) ∧
            c2 = Computation.map List.length (Computation.corec (fun ⟨l, s⟩ =>
              match Seq.destruct s with
              | none => Sum.inl l.reverse
              | some (none, s') => Sum.inr (l, s')
              | some (some a, s') => Sum.inr (a::l, s')) (l, s)))
      _ ⟨[], s, rfl, rfl⟩
theorem length_eq_map (s : WSeq α) : length s = Computation.map List.length (toList s) := by
  refine'
    Computation.eq_of_bisim
      (fun c1 c2 =>
        ∃ (l : List α) (s : WSeq α),
          c1 = Computation.corec (fun ⟨n, s⟩ =>
            match Seq.destruct s with
            | none => Sum.inl n
            | some (none, s') => Sum.inr (n, s')
            | some (some _, s') => Sum.inr (n + 1, s')) (l.length, s) ∧
            c2 = Computation.map List.length (Computation.corec (fun ⟨l, s⟩ =>
              match Seq.destruct s with
              | none => Sum.inl l.reverse
              | some (none, s') => Sum.inr (l, s')
              | some (some a, s') => Sum.inr (a::l, s')) (l, s)))
      _ ⟨[], s, rfl, rfl⟩
  

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
⊢ Computation.IsBisimulation fun c1 c2 =>
    ∃ l s,
      c1 =
          Computation.corec
            (fun x =>
              match x with
              | (n, s) =>
                match Seq.destruct s with
                | none => Sum.inl n
                | some (none, s') => Sum.inr (n, s')
                | some (some val, s') => Sum.inr (n + 1, s'))
            (List.length l, s) ∧
        c2 =
          Computation.map List.length
            (Computation.corec
              (fun x =>
                match x with
                | (l, s) =>
                  match Seq.destruct s with
                  | none => Sum.inl (List.reverse l)
                  | some (none, s') => Sum.inr (l, s')
                  | some (some a, s') => Sum.inr (a :: l, s'))
              (l, s))

Next tactic:
intro s1 s2 h