l3lab/ntp-mathlib huggingface dataset:
theorem map_parallel (f : α → β) (S) : map f (parallel S) = parallel (S.map (map f)) := by
  refine'
    eq_of_bisim
      (fun c1 c2 =>
        ∃ l S,
          c1 = map f (corec parallel.aux1 (l, S)) ∧
            c2 = corec parallel.aux1 (l.map (map f), S.map (map f)))
      _ ⟨[], S, rfl, rfl⟩
  intro c1 c2 h
  exact
    match c1, c2, h with
    | _, _, ⟨l, S, rfl, rfl⟩ => by
      have : parallel.aux2 (l.map (map f))
          = lmap f (rmap (List.map (map f)) (parallel.aux2 l)) := by
        simp only [parallel.aux2, rmap, lmap]
        induction' l with c l IH <;> simp
        rw [IH]
        cases List.foldr (fun c o =>
            match o with
            | Sum.inl a => Sum.inl a
            | Sum.inr ls => rmap (fun c' => c' :: ls) (destruct c)) (Sum.inr List.nil) l <;>
          simp [parallel.aux2]
        cases destruct c <;> simp
      simp only [BisimO, destruct_map, lmap, rmap, corec_eq, parallel.aux1._eq_1]
      rw [this]
      cases' parallel.aux2 l with a l' <;> 

Proof state:
case inl
α : Type u
β : Type v
f : α → β
S✝ : WSeq (Computation α)
c1 c2 : Computation β
h : ∃ l S, c1 = map f (corec parallel.aux1 (l, S)) ∧ c2 = corec parallel.aux1 (List.map (map f) l, WSeq.map (map f) S)
l : List (Computation α)
S : WSeq (Computation α)
this : parallel.aux2 (List.map (map f) l) = lmap f (rmap (List.map (map f)) (parallel.aux2 l))
a : α
⊢ match
    match
      match
        match
          match Sum.inl a with
          | Sum.inl a => Sum.inl a
          | Sum.inr b =>
            Sum.inr
              (match Seq.destruct S with
              | none => (b, Seq.nil)
              | some (none, S') => (b, S')
              | some (some c, S') => (c :: b, S')) with
        | Sum.inl a => Sum.inl a
        | Sum.inr b => Sum.inr (corec parallel.aux1 b) with
      | Sum.inl a => Sum.inl a
      | Sum.inr b => Sum.inr (map f b) with
    | Sum.inl a => Sum.inl (f a)
    | Sum.inr b => Sum.inr b,
    match
      match lmap f (rmap (List.map (map f)) (Sum.inl a)) with
      | Sum.inl a => Sum.inl a
      | Sum.inr b =>
        Sum.inr
          (match Seq.destruct (WSeq.map (map f) S) with
          | none => (b, Seq.nil)
          | some (none, S') => (b, S')
          | some (some c, S') => (c :: b, S')) with
    | Sum.inl a => Sum.inl a
    | Sum.inr b => Sum.inr (corec parallel.aux1 b) with
  | Sum.inl a, Sum.inl a' => a = a'
  | Sum.inr s, Sum.inr s' =>
    ∃ l S, s = map f (corec parallel.aux1 (l, S)) ∧ s' = corec parallel.aux1 (List.map (map f) l, WSeq.map (map f) S)
  | x, x_1 => False

Next tactic:
simp
theorem map_parallel (f : α → β) (S) : map f (parallel S) = parallel (S.map (map f)) := by
  refine'
    eq_of_bisim
      (fun c1 c2 =>
        ∃ l S,
          c1 = map f (corec parallel.aux1 (l, S)) ∧
            c2 = corec parallel.aux1 (l.map (map f), S.map (map f)))
      _ ⟨[], S, rfl, rfl⟩
  intro c1 c2 h
  exact
    match c1, c2, h with
    | _, _, ⟨l, S, rfl, rfl⟩ => by
      have : parallel.aux2 (l.map (map f))
          = lmap f (rmap (List.map (map f)) (parallel.aux2 l)) := by
        simp only [parallel.aux2, rmap, lmap]
        induction' l with c l IH <;> simp
        rw [IH]
        cases List.foldr (fun c o =>
            match o with
            | Sum.inl a => Sum.inl a
            | Sum.inr ls => rmap (fun c' => c' :: ls) (destruct c)) (Sum.inr List.nil) l <;>
          simp [parallel.aux2]
        cases destruct c <;> simp
      simp only [BisimO, destruct_map, lmap, rmap, corec_eq, parallel.aux1._eq_1]
      rw [this]
      cases' parallel.aux2 l with a l' <;> 

Proof state:
case inr
α : Type u
β : Type v
f : α → β
S✝ : WSeq (Computation α)
c1 c2 : Computation β
h : ∃ l S, c1 = map f (corec parallel.aux1 (l, S)) ∧ c2 = corec parallel.aux1 (List.map (map f) l, WSeq.map (map f) S)
l : List (Computation α)
S : WSeq (Computation α)
this : parallel.aux2 (List.map (map f) l) = lmap f (rmap (List.map (map f)) (parallel.aux2 l))
l' : List (Computation α)
⊢ match
    match
      match
        match
          match Sum.inr l' with
          | Sum.inl a => Sum.inl a
          | Sum.inr b =>
            Sum.inr
              (match Seq.destruct S with
              | none => (b, Seq.nil)
              | some (none, S') => (b, S')
              | some (some c, S') => (c :: b, S')) with
        | Sum.inl a => Sum.inl a
        | Sum.inr b => Sum.inr (corec parallel.aux1 b) with
      | Sum.inl a => Sum.inl a
      | Sum.inr b => Sum.inr (map f b) with
    | Sum.inl a => Sum.inl (f a)
    | Sum.inr b => Sum.inr b,
    match
      match lmap f (rmap (List.map (map f)) (Sum.inr l')) with
      | Sum.inl a => Sum.inl a
      | Sum.inr b =>
        Sum.inr
          (match Seq.destruct (WSeq.map (map f) S) with
          | none => (b, Seq.nil)
          | some (none, S') => (b, S')
          | some (some c, S') => (c :: b, S')) with
    | Sum.inl a => Sum.inl a
    | Sum.inr b => Sum.inr (corec parallel.aux1 b) with
  | Sum.inl a, Sum.inl a' => a = a'
  | Sum.inr s, Sum.inr s' =>
    ∃ l S, s = map f (corec parallel.aux1 (l, S)) ∧ s' = corec parallel.aux1 (List.map (map f) l, WSeq.map (map f) S)
  | x, x_1 => False

Next tactic:
simp
theorem map_parallel (f : α → β) (S) : map f (parallel S) = parallel (S.map (map f)) := by
  refine'
    eq_of_bisim
      (fun c1 c2 =>
        ∃ l S,
          c1 = map f (corec parallel.aux1 (l, S)) ∧
            c2 = corec parallel.aux1 (l.map (map f), S.map (map f)))
      _ ⟨[], S, rfl, rfl⟩
  intro c1 c2 h
  exact
    match c1, c2, h with
    | _, _, ⟨l, S, rfl, rfl⟩ => by
      have : parallel.aux2 (l.map (map f))
          = lmap f (rmap (List.map (map f)) (parallel.aux2 l)) := by
        simp only [parallel.aux2, rmap, lmap]
        induction' l with c l IH <;> simp
        rw [IH]
        cases List.foldr (fun c o =>
            match o with
            | Sum.inl a => Sum.inl a
            | Sum.inr ls => rmap (fun c' => c' :: ls) (destruct c)) (Sum.inr List.nil) l <;>
          simp [parallel.aux2]
        cases destruct c <;> simp
      simp only [BisimO, destruct_map, lmap, rmap, corec_eq, parallel.aux1._eq_1]
      rw [this]
      cases' parallel.aux2 l with a l' <;> simp
      

Proof state:
case inr
α : Type u
β : Type v
f : α → β
S✝ : WSeq (Computation α)
c1 c2 : Computation β
h : ∃ l S, c1 = map f (corec parallel.aux1 (l, S)) ∧ c2 = corec parallel.aux1 (List.map (map f) l, WSeq.map (map f) S)
l : List (Computation α)
S : WSeq (Computation α)
this : parallel.aux2 (List.map (map f) l) = lmap f (rmap (List.map (map f)) (parallel.aux2 l))
l' : List (Computation α)
⊢ ∃ l S_1,
    map f
          (corec parallel.aux1
            (match Seq.destruct S with
            | none => (l', Seq.nil)
            | some (none, S') => (l', S')
            | some (some c, S') => (c :: l', S'))) =
        map f (corec parallel.aux1 (l, S_1)) ∧
      corec parallel.aux1
          (match Seq.destruct (WSeq.map (map f) S) with
          | none => (List.map (map f) l', Seq.nil)
          | some (none, S') => (List.map (map f) l', S')
          | some (some c, S') => (c :: List.map (map f) l', S')) =
        corec parallel.aux1 (List.map (map f) l, WSeq.map (map f) S_1)

Next tactic:
induction' S using WSeq.recOn with c S S
theorem map_parallel (f : α → β) (S) : map f (parallel S) = parallel (S.map (map f)) := by
  refine'
    eq_of_bisim
      (fun c1 c2 =>
        ∃ l S,
          c1 = map f (corec parallel.aux1 (l, S)) ∧
            c2 = corec parallel.aux1 (l.map (map f), S.map (map f)))
      _ ⟨[], S, rfl, rfl⟩
  intro c1 c2 h
  exact
    match c1, c2, h with
    | _, _, ⟨l, S, rfl, rfl⟩ => by
      have : parallel.aux2 (l.map (map f))
          = lmap f (rmap (List.map (map f)) (parallel.aux2 l)) := by
        simp only [parallel.aux2, rmap, lmap]
        induction' l with c l IH <;> simp
        rw [IH]
        cases List.foldr (fun c o =>
            match o with
            | Sum.inl a => Sum.inl a
            | Sum.inr ls => rmap (fun c' => c' :: ls) (destruct c)) (Sum.inr List.nil) l <;>
          simp [parallel.aux2]
        cases destruct c <;> simp
      simp only [BisimO, destruct_map, lmap, rmap, corec_eq, parallel.aux1._eq_1]
      rw [this]
      cases' parallel.aux2 l with a l' <;> simp
      induction' S using WSeq.recOn with c S S <;> 

Proof state:
case inr.h1
α : Type u
β : Type v
f : α → β
S : WSeq (Computation α)
c1 c2 : Computation β
h : ∃ l S, c1 = map f (corec parallel.aux1 (l, S)) ∧ c2 = corec parallel.aux1 (List.map (map f) l, WSeq.map (map f) S)
l : List (Computation α)
this : parallel.aux2 (List.map (map f) l) = lmap f (rmap (List.map (map f)) (parallel.aux2 l))
l' : List (Computation α)
⊢ ∃ l S,
    map f
          (corec parallel.aux1
            (match Seq.destruct WSeq.nil with
            | none => (l', Seq.nil)
            | some (none, S') => (l', S')
            | some (some c, S') => (c :: l', S'))) =
        map f (corec parallel.aux1 (l, S)) ∧
      corec parallel.aux1
          (match Seq.destruct (WSeq.map (map f) WSeq.nil) with
          | none => (List.map (map f) l', Seq.nil)
          | some (none, S') => (List.map (map f) l', S')
          | some (some c, S') => (c :: List.map (map f) l', S')) =
        corec parallel.aux1 (List.map (map f) l, WSeq.map (map f) S)

Next tactic:
simp
theorem map_parallel (f : α → β) (S) : map f (parallel S) = parallel (S.map (map f)) := by
  refine'
    eq_of_bisim
      (fun c1 c2 =>
        ∃ l S,
          c1 = map f (corec parallel.aux1 (l, S)) ∧
            c2 = corec parallel.aux1 (l.map (map f), S.map (map f)))
      _ ⟨[], S, rfl, rfl⟩
  intro c1 c2 h
  exact
    match c1, c2, h with
    | _, _, ⟨l, S, rfl, rfl⟩ => by
      have : parallel.aux2 (l.map (map f))
          = lmap f (rmap (List.map (map f)) (parallel.aux2 l)) := by
        simp only [parallel.aux2, rmap, lmap]
        induction' l with c l IH <;> simp
        rw [IH]
        cases List.foldr (fun c o =>
            match o with
            | Sum.inl a => Sum.inl a
            | Sum.inr ls => rmap (fun c' => c' :: ls) (destruct c)) (Sum.inr List.nil) l <;>
          simp [parallel.aux2]
        cases destruct c <;> simp
      simp only [BisimO, destruct_map, lmap, rmap, corec_eq, parallel.aux1._eq_1]
      rw [this]
      cases' parallel.aux2 l with a l' <;> simp
      induction' S using WSeq.recOn with c S S <;> 

Proof state:
case inr.h2
α : Type u
β : Type v
f : α → β
S✝ : WSeq (Computation α)
c1 c2 : Computation β
h : ∃ l S, c1 = map f (corec parallel.aux1 (l, S)) ∧ c2 = corec parallel.aux1 (List.map (map f) l, WSeq.map (map f) S)
l : List (Computation α)
this : parallel.aux2 (List.map (map f) l) = lmap f (rmap (List.map (map f)) (parallel.aux2 l))
l' : List (Computation α)
c : Computation α
S : WSeq (Computation α)
⊢ ∃ l S_1,
    map f
          (corec parallel.aux1
            (match Seq.destruct (WSeq.cons c S) with
            | none => (l', Seq.nil)
            | some (none, S') => (l', S')
            | some (some c, S') => (c :: l', S'))) =
        map f (corec parallel.aux1 (l, S_1)) ∧
      corec parallel.aux1
          (match Seq.destruct (WSeq.map (map f) (WSeq.cons c S)) with
          | none => (List.map (map f) l', Seq.nil)
          | some (none, S') => (List.map (map f) l', S')
          | some (some c, S') => (c :: List.map (map f) l', S')) =
        corec parallel.aux1 (List.map (map f) l, WSeq.map (map f) S_1)

Next tactic:
simp
theorem map_parallel (f : α → β) (S) : map f (parallel S) = parallel (S.map (map f)) := by
  refine'
    eq_of_bisim
      (fun c1 c2 =>
        ∃ l S,
          c1 = map f (corec parallel.aux1 (l, S)) ∧
            c2 = corec parallel.aux1 (l.map (map f), S.map (map f)))
      _ ⟨[], S, rfl, rfl⟩
  intro c1 c2 h
  exact
    match c1, c2, h with
    | _, _, ⟨l, S, rfl, rfl⟩ => by
      have : parallel.aux2 (l.map (map f))
          = lmap f (rmap (List.map (map f)) (parallel.aux2 l)) := by
        simp only [parallel.aux2, rmap, lmap]
        induction' l with c l IH <;> simp
        rw [IH]
        cases List.foldr (fun c o =>
            match o with
            | Sum.inl a => Sum.inl a
            | Sum.inr ls => rmap (fun c' => c' :: ls) (destruct c)) (Sum.inr List.nil) l <;>
          simp [parallel.aux2]
        cases destruct c <;> simp
      simp only [BisimO, destruct_map, lmap, rmap, corec_eq, parallel.aux1._eq_1]
      rw [this]
      cases' parallel.aux2 l with a l' <;> simp
      induction' S using WSeq.recOn with c S S <;> 

Proof state:
case inr.h3
α : Type u
β : Type v
f : α → β
S✝ : WSeq (Computation α)
c1 c2 : Computation β
h : ∃ l S, c1 = map f (corec parallel.aux1 (l, S)) ∧ c2 = corec parallel.aux1 (List.map (map f) l, WSeq.map (map f) S)
l : List (Computation α)
this : parallel.aux2 (List.map (map f) l) = lmap f (rmap (List.map (map f)) (parallel.aux2 l))
l' : List (Computation α)
S : WSeq (Computation α)
⊢ ∃ l S_1,
    map f
          (corec parallel.aux1
            (match Seq.destruct (WSeq.think S) with
            | none => (l', Seq.nil)
            | some (none, S') => (l', S')
            | some (some c, S') => (c :: l', S'))) =
        map f (corec parallel.aux1 (l, S_1)) ∧
      corec parallel.aux1
          (match Seq.destruct (WSeq.map (map f) (WSeq.think S)) with
          | none => (List.map (map f) l', Seq.nil)
          | some (none, S') => (List.map (map f) l', S')
          | some (some c, S') => (c :: List.map (map f) l', S')) =
        corec parallel.aux1 (List.map (map f) l, WSeq.map (map f) S_1)

Next tactic:
simp
theorem map_parallel (f : α → β) (S) : map f (parallel S) = parallel (S.map (map f)) := by
  refine'
    eq_of_bisim
      (fun c1 c2 =>
        ∃ l S,
          c1 = map f (corec parallel.aux1 (l, S)) ∧
            c2 = corec parallel.aux1 (l.map (map f), S.map (map f)))
      _ ⟨[], S, rfl, rfl⟩
  intro c1 c2 h
  exact
    match c1, c2, h with
    | _, _, ⟨l, S, rfl, rfl⟩ => by
      have : parallel.aux2 (l.map (map f))
          = lmap f (rmap (List.map (map f)) (parallel.aux2 l)) := by
        simp only [parallel.aux2, rmap, lmap]
        induction' l with c l IH <;> simp
        rw [IH]
        cases List.foldr (fun c o =>
            match o with
            | Sum.inl a => Sum.inl a
            | Sum.inr ls => rmap (fun c' => c' :: ls) (destruct c)) (Sum.inr List.nil) l <;>
          simp [parallel.aux2]
        cases destruct c <;> simp
      simp only [BisimO, destruct_map, lmap, rmap, corec_eq, parallel.aux1._eq_1]
      rw [this]
      cases' parallel.aux2 l with a l' <;> simp
      induction' S using WSeq.recOn with c S S <;> simp <;>
        

Proof state:
case inr.h1
α : Type u
β : Type v
f : α → β
S : WSeq (Computation α)
c1 c2 : Computation β
h : ∃ l S, c1 = map f (corec parallel.aux1 (l, S)) ∧ c2 = corec parallel.aux1 (List.map (map f) l, WSeq.map (map f) S)
l : List (Computation α)
this : parallel.aux2 (List.map (map f) l) = lmap f (rmap (List.map (map f)) (parallel.aux2 l))
l' : List (Computation α)
⊢ ∃ l S,
    map f (corec parallel.aux1 (l', Seq.nil)) = map f (corec parallel.aux1 (l, S)) ∧
      corec parallel.aux1 (List.map (map f) l', Seq.nil) = corec parallel.aux1 (List.map (map f) l, WSeq.map (map f) S)

Next tactic:
exact ⟨_, _, rfl, rfl⟩
theorem map_parallel (f : α → β) (S) : map f (parallel S) = parallel (S.map (map f)) := by
  refine'
    eq_of_bisim
      (fun c1 c2 =>
        ∃ l S,
          c1 = map f (corec parallel.aux1 (l, S)) ∧
            c2 = corec parallel.aux1 (l.map (map f), S.map (map f)))
      _ ⟨[], S, rfl, rfl⟩
  intro c1 c2 h
  exact
    match c1, c2, h with
    | _, _, ⟨l, S, rfl, rfl⟩ => by
      have : parallel.aux2 (l.map (map f))
          = lmap f (rmap (List.map (map f)) (parallel.aux2 l)) := by
        simp only [parallel.aux2, rmap, lmap]
        induction' l with c l IH <;> simp
        rw [IH]
        cases List.foldr (fun c o =>
            match o with
            | Sum.inl a => Sum.inl a
            | Sum.inr ls => rmap (fun c' => c' :: ls) (destruct c)) (Sum.inr List.nil) l <;>
          simp [parallel.aux2]
        cases destruct c <;> simp
      simp only [BisimO, destruct_map, lmap, rmap, corec_eq, parallel.aux1._eq_1]
      rw [this]
      cases' parallel.aux2 l with a l' <;> simp
      induction' S using WSeq.recOn with c S S <;> simp <;>
        

Proof state:
case inr.h2
α : Type u
β : Type v
f : α → β
S✝ : WSeq (Computation α)
c1 c2 : Computation β
h : ∃ l S, c1 = map f (corec parallel.aux1 (l, S)) ∧ c2 = corec parallel.aux1 (List.map (map f) l, WSeq.map (map f) S)
l : List (Computation α)
this : parallel.aux2 (List.map (map f) l) = lmap f (rmap (List.map (map f)) (parallel.aux2 l))
l' : List (Computation α)
c : Computation α
S : WSeq (Computation α)
⊢ ∃ l S_1,
    map f (corec parallel.aux1 (c :: l', S)) = map f (corec parallel.aux1 (l, S_1)) ∧
      corec parallel.aux1 (map f c :: List.map (map f) l', WSeq.map (map f) S) =
        corec parallel.aux1 (List.map (map f) l, WSeq.map (map f) S_1)

Next tactic:
exact ⟨_, _, rfl, rfl⟩
theorem map_parallel (f : α → β) (S) : map f (parallel S) = parallel (S.map (map f)) := by
  refine'
    eq_of_bisim
      (fun c1 c2 =>
        ∃ l S,
          c1 = map f (corec parallel.aux1 (l, S)) ∧
            c2 = corec parallel.aux1 (l.map (map f), S.map (map f)))
      _ ⟨[], S, rfl, rfl⟩
  intro c1 c2 h
  exact
    match c1, c2, h with
    | _, _, ⟨l, S, rfl, rfl⟩ => by
      have : parallel.aux2 (l.map (map f))
          = lmap f (rmap (List.map (map f)) (parallel.aux2 l)) := by
        simp only [parallel.aux2, rmap, lmap]
        induction' l with c l IH <;> simp
        rw [IH]
        cases List.foldr (fun c o =>
            match o with
            | Sum.inl a => Sum.inl a
            | Sum.inr ls => rmap (fun c' => c' :: ls) (destruct c)) (Sum.inr List.nil) l <;>
          simp [parallel.aux2]
        cases destruct c <;> simp
      simp only [BisimO, destruct_map, lmap, rmap, corec_eq, parallel.aux1._eq_1]
      rw [this]
      cases' parallel.aux2 l with a l' <;> simp
      induction' S using WSeq.recOn with c S S <;> simp <;>
        

Proof state:
case inr.h3
α : Type u
β : Type v
f : α → β
S✝ : WSeq (Computation α)
c1 c2 : Computation β
h : ∃ l S, c1 = map f (corec parallel.aux1 (l, S)) ∧ c2 = corec parallel.aux1 (List.map (map f) l, WSeq.map (map f) S)
l : List (Computation α)
this : parallel.aux2 (List.map (map f) l) = lmap f (rmap (List.map (map f)) (parallel.aux2 l))
l' : List (Computation α)
S : WSeq (Computation α)
⊢ ∃ l S_1,
    map f (corec parallel.aux1 (l', S)) = map f (corec parallel.aux1 (l, S_1)) ∧
      corec parallel.aux1 (List.map (map f) l', WSeq.map (map f) S) =
        corec parallel.aux1 (List.map (map f) l, WSeq.map (map f) S_1)

Next tactic:
exact ⟨_, _, rfl, rfl⟩
theorem parallel_empty (S : WSeq (Computation α)) (h : S.head ~> none) : parallel S = empty _ :=
  eq_empty_of_not_terminates fun ⟨⟨a, m⟩⟩ => by
    

Proof state:
α : Type u
β : Type v
S : WSeq (Computation α)
h : WSeq.head S ~> none
x✝ : Terminates (parallel S)
a : α
m : a ∈ parallel S
⊢ False

Next tactic:
let ⟨c, cs, _⟩ := exists_of_mem_parallel m
theorem parallel_empty (S : WSeq (Computation α)) (h : S.head ~> none) : parallel S = empty _ :=
  eq_empty_of_not_terminates fun ⟨⟨a, m⟩⟩ => by
    let ⟨c, cs, _⟩ := exists_of_mem_parallel m
    

Proof state:
α : Type u
β : Type v
S : WSeq (Computation α)
h : WSeq.head S ~> none
x✝ : Terminates (parallel S)
a : α
m : a ∈ parallel S
c : Computation α
cs : c ∈ S
right✝ : a ∈ c
⊢ False

Next tactic:
let ⟨n, nm⟩ := WSeq.exists_get?_of_mem cs
theorem parallel_empty (S : WSeq (Computation α)) (h : S.head ~> none) : parallel S = empty _ :=
  eq_empty_of_not_terminates fun ⟨⟨a, m⟩⟩ => by
    let ⟨c, cs, _⟩ := exists_of_mem_parallel m
    let ⟨n, nm⟩ := WSeq.exists_get?_of_mem cs
    

Proof state:
α : Type u
β : Type v
S : WSeq (Computation α)
h : WSeq.head S ~> none
x✝ : Terminates (parallel S)
a : α
m : a ∈ parallel S
c : Computation α
cs : c ∈ S
right✝ : a ∈ c
n : ℕ
nm : some c ∈ WSeq.get? S n
⊢ False

Next tactic:
let ⟨c', h'⟩ := WSeq.head_some_of_get?_some nm
theorem parallel_empty (S : WSeq (Computation α)) (h : S.head ~> none) : parallel S = empty _ :=
  eq_empty_of_not_terminates fun ⟨⟨a, m⟩⟩ => by
    let ⟨c, cs, _⟩ := exists_of_mem_parallel m
    let ⟨n, nm⟩ := WSeq.exists_get?_of_mem cs
    let ⟨c', h'⟩ := WSeq.head_some_of_get?_some nm
    

Proof state:
α : Type u
β : Type v
S : WSeq (Computation α)
h : WSeq.head S ~> none
x✝ : Terminates (parallel S)
a : α
m : a ∈ parallel S
c : Computation α
cs : c ∈ S
right✝ : a ∈ c
n : ℕ
nm : some c ∈ WSeq.get? S n
c' : Computation α
h' : some c' ∈ WSeq.head S
⊢ False

Next tactic:
injection h h'
def parallelRec {S : WSeq (Computation α)} (C : α → Sort v) (H : ∀ s ∈ S, ∀ a ∈ s, C a) {a}
    (h : a ∈ parallel S) : C a := by
  

Proof state:
α : Type u
β : Type v
S : WSeq (Computation α)
C : α → Sort v
H : (s : Computation α) → s ∈ S → (a : α) → a ∈ s → C a
a : α
h : a ∈ parallel S
⊢ C a

Next tactic:
let T : WSeq (Computation (α × Computation α)) := S.map fun c => c.map fun a => (a, c)
def parallelRec {S : WSeq (Computation α)} (C : α → Sort v) (H : ∀ s ∈ S, ∀ a ∈ s, C a) {a}
    (h : a ∈ parallel S) : C a := by
  let T : WSeq (Computation (α × Computation α)) := S.map fun c => c.map fun a => (a, c)
  

Proof state:
α : Type u
β : Type v
S : WSeq (Computation α)
C : α → Sort v
H : (s : Computation α) → s ∈ S → (a : α) → a ∈ s → C a
a : α
h : a ∈ parallel S
T : WSeq (Computation (α × Computation α)) := WSeq.map (fun c => map (fun a => (a, c)) c) S
⊢ C a

Next tactic:
have : S = T.map (map fun c => c.1) := by
    rw [← WSeq.map_comp]
    refine' (WSeq.map_id _).symm.trans (congr_arg (fun f => WSeq.map f S) _)
    funext c
    dsimp [id, Function.comp_def]
    rw [← map_comp]
    exact (map_id _).symm
def parallelRec {S : WSeq (Computation α)} (C : α → Sort v) (H : ∀ s ∈ S, ∀ a ∈ s, C a) {a}
    (h : a ∈ parallel S) : C a := by
  let T : WSeq (Computation (α × Computation α)) := S.map fun c => c.map fun a => (a, c)
  have : S = T.map (map fun c => c.1) := by
    

Proof state:
α : Type u
β : Type v
S : WSeq (Computation α)
C : α → Sort v
H : (s : Computation α) → s ∈ S → (a : α) → a ∈ s → C a
a : α
h : a ∈ parallel S
T : WSeq (Computation (α × Computation α)) := WSeq.map (fun c => map (fun a => (a, c)) c) S
⊢ S = WSeq.map (map fun c => c.1) T

Next tactic:
rw [← WSeq.map_comp]
def parallelRec {S : WSeq (Computation α)} (C : α → Sort v) (H : ∀ s ∈ S, ∀ a ∈ s, C a) {a}
    (h : a ∈ parallel S) : C a := by
  let T : WSeq (Computation (α × Computation α)) := S.map fun c => c.map fun a => (a, c)
  have : S = T.map (map fun c => c.1) := by
    rw [← WSeq.map_comp]
    

Proof state:
α : Type u
β : Type v
S : WSeq (Computation α)
C : α → Sort v
H : (s : Computation α) → s ∈ S → (a : α) → a ∈ s → C a
a : α
h : a ∈ parallel S
T : WSeq (Computation (α × Computation α)) := WSeq.map (fun c => map (fun a => (a, c)) c) S
⊢ S = WSeq.map ((map fun c => c.1) ∘ fun c => map (fun a => (a, c)) c) S

Next tactic:
refine' (WSeq.map_id _).symm.trans (congr_arg (fun f => WSeq.map f S) _)
def parallelRec {S : WSeq (Computation α)} (C : α → Sort v) (H : ∀ s ∈ S, ∀ a ∈ s, C a) {a}
    (h : a ∈ parallel S) : C a := by
  let T : WSeq (Computation (α × Computation α)) := S.map fun c => c.map fun a => (a, c)
  have : S = T.map (map fun c => c.1) := by
    rw [← WSeq.map_comp]
    refine' (WSeq.map_id _).symm.trans (congr_arg (fun f => WSeq.map f S) _)
    

Proof state:
α : Type u
β : Type v
S : WSeq (Computation α)
C : α → Sort v
H : (s : Computation α) → s ∈ S → (a : α) → a ∈ s → C a
a : α
h : a ∈ parallel S
T : WSeq (Computation (α × Computation α)) := WSeq.map (fun c => map (fun a => (a, c)) c) S
⊢ id = (map fun c => c.1) ∘ fun c => map (fun a => (a, c)) c

Next tactic:
funext c
def parallelRec {S : WSeq (Computation α)} (C : α → Sort v) (H : ∀ s ∈ S, ∀ a ∈ s, C a) {a}
    (h : a ∈ parallel S) : C a := by
  let T : WSeq (Computation (α × Computation α)) := S.map fun c => c.map fun a => (a, c)
  have : S = T.map (map fun c => c.1) := by
    rw [← WSeq.map_comp]
    refine' (WSeq.map_id _).symm.trans (congr_arg (fun f => WSeq.map f S) _)
    funext c
    

Proof state:
case h
α : Type u
β : Type v
S : WSeq (Computation α)
C : α → Sort v
H : (s : Computation α) → s ∈ S → (a : α) → a ∈ s → C a
a : α
h : a ∈ parallel S
T : WSeq (Computation (α × Computation α)) := WSeq.map (fun c => map (fun a => (a, c)) c) S
c : Computation α
⊢ id c = ((map fun c => c.1) ∘ fun c => map (fun a => (a, c)) c) c

Next tactic:
dsimp [id, Function.comp_def]