l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  cases' s with a s
  -- Porting note: Was `simp [bind, map]`.
  

Proof state:
case mk
α : Type u
β : Type v
γ : Type w
f : α → Seq1 β
g : β → Seq1 γ
a : α
s : Seq α
⊢ bind (bind (a, s) f) g = bind (a, s) fun x => bind (f x) g

Next tactic:
simp only [bind, map_pair, map_join]
@[simp]
theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  cases' s with a s
  -- Porting note: Was `simp [bind, map]`.
  simp only [bind, map_pair, map_join]
  

Proof state:
case mk
α : Type u
β : Type v
γ : Type w
f : α → Seq1 β
g : β → Seq1 γ
a : α
s : Seq α
⊢ join (join (map g (f a), Seq.map (map g) (Seq.map f s))) =
    join (join (map g (f a)), Seq.map (fun x => join (map g (f x))) s)

Next tactic:
rw [← map_comp]
@[simp]
theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  cases' s with a s
  -- Porting note: Was `simp [bind, map]`.
  simp only [bind, map_pair, map_join]
  rw [← map_comp]
  

Proof state:
case mk
α : Type u
β : Type v
γ : Type w
f : α → Seq1 β
g : β → Seq1 γ
a : α
s : Seq α
⊢ join (join (map g (f a), Seq.map (map g ∘ f) s)) = join (join (map g (f a)), Seq.map (fun x => join (map g (f x))) s)

Next tactic:
simp only [show (fun x => join (map g (f x))) = join ∘ (map g ∘ f) from rfl]
@[simp]
theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  cases' s with a s
  -- Porting note: Was `simp [bind, map]`.
  simp only [bind, map_pair, map_join]
  rw [← map_comp]
  simp only [show (fun x => join (map g (f x))) = join ∘ (map g ∘ f) from rfl]
  

Proof state:
case mk
α : Type u
β : Type v
γ : Type w
f : α → Seq1 β
g : β → Seq1 γ
a : α
s : Seq α
⊢ join (join (map g (f a), Seq.map (map g ∘ f) s)) = join (join (map g (f a)), Seq.map (join ∘ map g ∘ f) s)

Next tactic:
rw [map_comp _ join]
@[simp]
theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  cases' s with a s
  -- Porting note: Was `simp [bind, map]`.
  simp only [bind, map_pair, map_join]
  rw [← map_comp]
  simp only [show (fun x => join (map g (f x))) = join ∘ (map g ∘ f) from rfl]
  rw [map_comp _ join]
  

Proof state:
case mk
α : Type u
β : Type v
γ : Type w
f : α → Seq1 β
g : β → Seq1 γ
a : α
s : Seq α
⊢ join (join (map g (f a), Seq.map (map g ∘ f) s)) = join (join (map g (f a)), Seq.map join (Seq.map (map g ∘ f) s))

Next tactic:
generalize Seq.map (map g ∘ f) s = SS
@[simp]
theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  cases' s with a s
  -- Porting note: Was `simp [bind, map]`.
  simp only [bind, map_pair, map_join]
  rw [← map_comp]
  simp only [show (fun x => join (map g (f x))) = join ∘ (map g ∘ f) from rfl]
  rw [map_comp _ join]
  generalize Seq.map (map g ∘ f) s = SS
  

Proof state:
case mk
α : Type u
β : Type v
γ : Type w
f : α → Seq1 β
g : β → Seq1 γ
a : α
s : Seq α
SS : Seq (Seq1 (Seq1 γ))
⊢ join (join (map g (f a), SS)) = join (join (map g (f a)), Seq.map join SS)

Next tactic:
rcases map g (f a) with ⟨⟨a, s⟩, S⟩
@[simp]
theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  cases' s with a s
  -- Porting note: Was `simp [bind, map]`.
  simp only [bind, map_pair, map_join]
  rw [← map_comp]
  simp only [show (fun x => join (map g (f x))) = join ∘ (map g ∘ f) from rfl]
  rw [map_comp _ join]
  generalize Seq.map (map g ∘ f) s = SS
  rcases map g (f a) with ⟨⟨a, s⟩, S⟩
  -- Porting note: Instead of `apply recOn s <;> intros`, `induction'` are used to
  --   give names to variables.
  

Proof state:
case mk.mk.mk
α : Type u
β : Type v
γ : Type w
f : α → Seq1 β
g : β → Seq1 γ
a✝ : α
s✝ : Seq α
SS : Seq (Seq1 (Seq1 γ))
S : Seq (Seq1 γ)
a : γ
s : Seq γ
⊢ join (join (((a, s), S), SS)) = join (join ((a, s), S), Seq.map join SS)

Next tactic:
induction' s using recOn with x s_1
@[simp]
theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  cases' s with a s
  -- Porting note: Was `simp [bind, map]`.
  simp only [bind, map_pair, map_join]
  rw [← map_comp]
  simp only [show (fun x => join (map g (f x))) = join ∘ (map g ∘ f) from rfl]
  rw [map_comp _ join]
  generalize Seq.map (map g ∘ f) s = SS
  rcases map g (f a) with ⟨⟨a, s⟩, S⟩
  -- Porting note: Instead of `apply recOn s <;> intros`, `induction'` are used to
  --   give names to variables.
  induction' s using recOn with x s_1 <;> 

Proof state:
case mk.mk.mk.h1
α : Type u
β : Type v
γ : Type w
f : α → Seq1 β
g : β → Seq1 γ
a✝ : α
s : Seq α
SS : Seq (Seq1 (Seq1 γ))
S : Seq (Seq1 γ)
a : γ
⊢ join (join (((a, nil), S), SS)) = join (join ((a, nil), S), Seq.map join SS)

Next tactic:
induction' S using recOn with x_1 s_2
@[simp]
theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  cases' s with a s
  -- Porting note: Was `simp [bind, map]`.
  simp only [bind, map_pair, map_join]
  rw [← map_comp]
  simp only [show (fun x => join (map g (f x))) = join ∘ (map g ∘ f) from rfl]
  rw [map_comp _ join]
  generalize Seq.map (map g ∘ f) s = SS
  rcases map g (f a) with ⟨⟨a, s⟩, S⟩
  -- Porting note: Instead of `apply recOn s <;> intros`, `induction'` are used to
  --   give names to variables.
  induction' s using recOn with x s_1 <;> 

Proof state:
case mk.mk.mk.h2
α : Type u
β : Type v
γ : Type w
f : α → Seq1 β
g : β → Seq1 γ
a✝ : α
s : Seq α
SS : Seq (Seq1 (Seq1 γ))
S : Seq (Seq1 γ)
a x : γ
s_1 : Seq γ
⊢ join (join (((a, Seq.cons x s_1), S), SS)) = join (join ((a, Seq.cons x s_1), S), Seq.map join SS)

Next tactic:
induction' S using recOn with x_1 s_2
@[simp]
theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  cases' s with a s
  -- Porting note: Was `simp [bind, map]`.
  simp only [bind, map_pair, map_join]
  rw [← map_comp]
  simp only [show (fun x => join (map g (f x))) = join ∘ (map g ∘ f) from rfl]
  rw [map_comp _ join]
  generalize Seq.map (map g ∘ f) s = SS
  rcases map g (f a) with ⟨⟨a, s⟩, S⟩
  -- Porting note: Instead of `apply recOn s <;> intros`, `induction'` are used to
  --   give names to variables.
  induction' s using recOn with x s_1 <;> induction' S using recOn with x_1 s_2 <;> 

Proof state:
case mk.mk.mk.h1.h1
α : Type u
β : Type v
γ : Type w
f : α → Seq1 β
g : β → Seq1 γ
a✝ : α
s : Seq α
SS : Seq (Seq1 (Seq1 γ))
a : γ
⊢ join (join (((a, nil), nil), SS)) = join (join ((a, nil), nil), Seq.map join SS)

Next tactic:
simp
@[simp]
theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  cases' s with a s
  -- Porting note: Was `simp [bind, map]`.
  simp only [bind, map_pair, map_join]
  rw [← map_comp]
  simp only [show (fun x => join (map g (f x))) = join ∘ (map g ∘ f) from rfl]
  rw [map_comp _ join]
  generalize Seq.map (map g ∘ f) s = SS
  rcases map g (f a) with ⟨⟨a, s⟩, S⟩
  -- Porting note: Instead of `apply recOn s <;> intros`, `induction'` are used to
  --   give names to variables.
  induction' s using recOn with x s_1 <;> induction' S using recOn with x_1 s_2 <;> 

Proof state:
case mk.mk.mk.h1.h2
α : Type u
β : Type v
γ : Type w
f : α → Seq1 β
g : β → Seq1 γ
a✝ : α
s : Seq α
SS : Seq (Seq1 (Seq1 γ))
a : γ
x_1 : Seq1 γ
s_2 : Seq (Seq1 γ)
⊢ join (join (((a, nil), Seq.cons x_1 s_2), SS)) = join (join ((a, nil), Seq.cons x_1 s_2), Seq.map join SS)

Next tactic:
simp
@[simp]
theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  cases' s with a s
  -- Porting note: Was `simp [bind, map]`.
  simp only [bind, map_pair, map_join]
  rw [← map_comp]
  simp only [show (fun x => join (map g (f x))) = join ∘ (map g ∘ f) from rfl]
  rw [map_comp _ join]
  generalize Seq.map (map g ∘ f) s = SS
  rcases map g (f a) with ⟨⟨a, s⟩, S⟩
  -- Porting note: Instead of `apply recOn s <;> intros`, `induction'` are used to
  --   give names to variables.
  induction' s using recOn with x s_1 <;> induction' S using recOn with x_1 s_2 <;> 

Proof state:
case mk.mk.mk.h2.h1
α : Type u
β : Type v
γ : Type w
f : α → Seq1 β
g : β → Seq1 γ
a✝ : α
s : Seq α
SS : Seq (Seq1 (Seq1 γ))
a x : γ
s_1 : Seq γ
⊢ join (join (((a, Seq.cons x s_1), nil), SS)) = join (join ((a, Seq.cons x s_1), nil), Seq.map join SS)

Next tactic:
simp
@[simp]
theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  cases' s with a s
  -- Porting note: Was `simp [bind, map]`.
  simp only [bind, map_pair, map_join]
  rw [← map_comp]
  simp only [show (fun x => join (map g (f x))) = join ∘ (map g ∘ f) from rfl]
  rw [map_comp _ join]
  generalize Seq.map (map g ∘ f) s = SS
  rcases map g (f a) with ⟨⟨a, s⟩, S⟩
  -- Porting note: Instead of `apply recOn s <;> intros`, `induction'` are used to
  --   give names to variables.
  induction' s using recOn with x s_1 <;> induction' S using recOn with x_1 s_2 <;> 

Proof state:
case mk.mk.mk.h2.h2
α : Type u
β : Type v
γ : Type w
f : α → Seq1 β
g : β → Seq1 γ
a✝ : α
s : Seq α
SS : Seq (Seq1 (Seq1 γ))
a x : γ
s_1 : Seq γ
x_1 : Seq1 γ
s_2 : Seq (Seq1 γ)
⊢ join (join (((a, Seq.cons x s_1), Seq.cons x_1 s_2), SS)) =
    join (join ((a, Seq.cons x s_1), Seq.cons x_1 s_2), Seq.map join SS)

Next tactic:
simp
@[simp]
theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  cases' s with a s
  -- Porting note: Was `simp [bind, map]`.
  simp only [bind, map_pair, map_join]
  rw [← map_comp]
  simp only [show (fun x => join (map g (f x))) = join ∘ (map g ∘ f) from rfl]
  rw [map_comp _ join]
  generalize Seq.map (map g ∘ f) s = SS
  rcases map g (f a) with ⟨⟨a, s⟩, S⟩
  -- Porting note: Instead of `apply recOn s <;> intros`, `induction'` are used to
  --   give names to variables.
  induction' s using recOn with x s_1 <;> induction' S using recOn with x_1 s_2 <;> simp
  · 

Proof state:
case mk.mk.mk.h1.h2
α : Type u
β : Type v
γ : Type w
f : α → Seq1 β
g : β → Seq1 γ
a✝ : α
s : Seq α
SS : Seq (Seq1 (Seq1 γ))
a : γ
x_1 : Seq1 γ
s_2 : Seq (Seq1 γ)
⊢ (a, Seq.join (Seq.cons x_1 (append s_2 (Seq.join SS)))) = join ((a, Seq.join (Seq.cons x_1 s_2)), Seq.map join SS)

Next tactic:
cases' x_1 with x t
@[simp]
theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  cases' s with a s
  -- Porting note: Was `simp [bind, map]`.
  simp only [bind, map_pair, map_join]
  rw [← map_comp]
  simp only [show (fun x => join (map g (f x))) = join ∘ (map g ∘ f) from rfl]
  rw [map_comp _ join]
  generalize Seq.map (map g ∘ f) s = SS
  rcases map g (f a) with ⟨⟨a, s⟩, S⟩
  -- Porting note: Instead of `apply recOn s <;> intros`, `induction'` are used to
  --   give names to variables.
  induction' s using recOn with x s_1 <;> induction' S using recOn with x_1 s_2 <;> simp
  · cases' x_1 with x t
    

Proof state:
case mk.mk.mk.h1.h2.mk
α : Type u
β : Type v
γ : Type w
f : α → Seq1 β
g : β → Seq1 γ
a✝ : α
s : Seq α
SS : Seq (Seq1 (Seq1 γ))
a : γ
s_2 : Seq (Seq1 γ)
x : γ
t : Seq γ
⊢ (a, Seq.join (Seq.cons (x, t) (append s_2 (Seq.join SS)))) =
    join ((a, Seq.join (Seq.cons (x, t) s_2)), Seq.map join SS)

Next tactic:
apply recOn t
@[simp]
theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  cases' s with a s
  -- Porting note: Was `simp [bind, map]`.
  simp only [bind, map_pair, map_join]
  rw [← map_comp]
  simp only [show (fun x => join (map g (f x))) = join ∘ (map g ∘ f) from rfl]
  rw [map_comp _ join]
  generalize Seq.map (map g ∘ f) s = SS
  rcases map g (f a) with ⟨⟨a, s⟩, S⟩
  -- Porting note: Instead of `apply recOn s <;> intros`, `induction'` are used to
  --   give names to variables.
  induction' s using recOn with x s_1 <;> induction' S using recOn with x_1 s_2 <;> simp
  · cases' x_1 with x t
    apply recOn t <;> 

Proof state:
case mk.mk.mk.h1.h2.mk.h1
α : Type u
β : Type v
γ : Type w
f : α → Seq1 β
g : β → Seq1 γ
a✝ : α
s : Seq α
SS : Seq (Seq1 (Seq1 γ))
a : γ
s_2 : Seq (Seq1 γ)
x : γ
t : Seq γ
⊢ (a, Seq.join (Seq.cons (x, nil) (append s_2 (Seq.join SS)))) =
    join ((a, Seq.join (Seq.cons (x, nil) s_2)), Seq.map join SS)

Next tactic:
intros
@[simp]
theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  cases' s with a s
  -- Porting note: Was `simp [bind, map]`.
  simp only [bind, map_pair, map_join]
  rw [← map_comp]
  simp only [show (fun x => join (map g (f x))) = join ∘ (map g ∘ f) from rfl]
  rw [map_comp _ join]
  generalize Seq.map (map g ∘ f) s = SS
  rcases map g (f a) with ⟨⟨a, s⟩, S⟩
  -- Porting note: Instead of `apply recOn s <;> intros`, `induction'` are used to
  --   give names to variables.
  induction' s using recOn with x s_1 <;> induction' S using recOn with x_1 s_2 <;> simp
  · cases' x_1 with x t
    apply recOn t <;> 

Proof state:
case mk.mk.mk.h1.h2.mk.h2
α : Type u
β : Type v
γ : Type w
f : α → Seq1 β
g : β → Seq1 γ
a✝ : α
s : Seq α
SS : Seq (Seq1 (Seq1 γ))
a : γ
s_2 : Seq (Seq1 γ)
x : γ
t : Seq γ
⊢ ∀ (x_1 : γ) (s : Seq γ),
    (a, Seq.join (Seq.cons (x, Seq.cons x_1 s) (append s_2 (Seq.join SS)))) =
      join ((a, Seq.join (Seq.cons (x, Seq.cons x_1 s) s_2)), Seq.map join SS)

Next tactic:
intros
@[simp]
theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  cases' s with a s
  -- Porting note: Was `simp [bind, map]`.
  simp only [bind, map_pair, map_join]
  rw [← map_comp]
  simp only [show (fun x => join (map g (f x))) = join ∘ (map g ∘ f) from rfl]
  rw [map_comp _ join]
  generalize Seq.map (map g ∘ f) s = SS
  rcases map g (f a) with ⟨⟨a, s⟩, S⟩
  -- Porting note: Instead of `apply recOn s <;> intros`, `induction'` are used to
  --   give names to variables.
  induction' s using recOn with x s_1 <;> induction' S using recOn with x_1 s_2 <;> simp
  · cases' x_1 with x t
    apply recOn t <;> intros <;> 

Proof state:
case mk.mk.mk.h1.h2.mk.h1
α : Type u
β : Type v
γ : Type w
f : α → Seq1 β
g : β → Seq1 γ
a✝ : α
s : Seq α
SS : Seq (Seq1 (Seq1 γ))
a : γ
s_2 : Seq (Seq1 γ)
x : γ
t : Seq γ
⊢ (a, Seq.join (Seq.cons (x, nil) (append s_2 (Seq.join SS)))) =
    join ((a, Seq.join (Seq.cons (x, nil) s_2)), Seq.map join SS)

Next tactic:
simp
@[simp]
theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  cases' s with a s
  -- Porting note: Was `simp [bind, map]`.
  simp only [bind, map_pair, map_join]
  rw [← map_comp]
  simp only [show (fun x => join (map g (f x))) = join ∘ (map g ∘ f) from rfl]
  rw [map_comp _ join]
  generalize Seq.map (map g ∘ f) s = SS
  rcases map g (f a) with ⟨⟨a, s⟩, S⟩
  -- Porting note: Instead of `apply recOn s <;> intros`, `induction'` are used to
  --   give names to variables.
  induction' s using recOn with x s_1 <;> induction' S using recOn with x_1 s_2 <;> simp
  · cases' x_1 with x t
    apply recOn t <;> intros <;> 

Proof state:
case mk.mk.mk.h1.h2.mk.h2
α : Type u
β : Type v
γ : Type w
f : α → Seq1 β
g : β → Seq1 γ
a✝ : α
s : Seq α
SS : Seq (Seq1 (Seq1 γ))
a : γ
s_2 : Seq (Seq1 γ)
x : γ
t : Seq γ
x✝ : γ
s✝ : Seq γ
⊢ (a, Seq.join (Seq.cons (x, Seq.cons x✝ s✝) (append s_2 (Seq.join SS)))) =
    join ((a, Seq.join (Seq.cons (x, Seq.cons x✝ s✝) s_2)), Seq.map join SS)

Next tactic:
simp
@[simp]
theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  cases' s with a s
  -- Porting note: Was `simp [bind, map]`.
  simp only [bind, map_pair, map_join]
  rw [← map_comp]
  simp only [show (fun x => join (map g (f x))) = join ∘ (map g ∘ f) from rfl]
  rw [map_comp _ join]
  generalize Seq.map (map g ∘ f) s = SS
  rcases map g (f a) with ⟨⟨a, s⟩, S⟩
  -- Porting note: Instead of `apply recOn s <;> intros`, `induction'` are used to
  --   give names to variables.
  induction' s using recOn with x s_1 <;> induction' S using recOn with x_1 s_2 <;> simp
  · cases' x_1 with x t
    apply recOn t <;> intros <;> simp
  · 

Proof state:
case mk.mk.mk.h2.h2
α : Type u
β : Type v
γ : Type w
f : α → Seq1 β
g : β → Seq1 γ
a✝ : α
s : Seq α
SS : Seq (Seq1 (Seq1 γ))
a x : γ
s_1 : Seq γ
x_1 : Seq1 γ
s_2 : Seq (Seq1 γ)
⊢ (a, Seq.cons x (append s_1 (Seq.join (Seq.cons x_1 (append s_2 (Seq.join SS)))))) =
    (a, Seq.cons x (append s_1 (append (Seq.join (Seq.cons x_1 s_2)) (Seq.join (Seq.map join SS)))))

Next tactic:
cases' x_1 with y t
@[simp]
theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  cases' s with a s
  -- Porting note: Was `simp [bind, map]`.
  simp only [bind, map_pair, map_join]
  rw [← map_comp]
  simp only [show (fun x => join (map g (f x))) = join ∘ (map g ∘ f) from rfl]
  rw [map_comp _ join]
  generalize Seq.map (map g ∘ f) s = SS
  rcases map g (f a) with ⟨⟨a, s⟩, S⟩
  -- Porting note: Instead of `apply recOn s <;> intros`, `induction'` are used to
  --   give names to variables.
  induction' s using recOn with x s_1 <;> induction' S using recOn with x_1 s_2 <;> simp
  · cases' x_1 with x t
    apply recOn t <;> intros <;> simp
  · cases' x_1 with y t; 

Proof state:
case mk.mk.mk.h2.h2.mk
α : Type u
β : Type v
γ : Type w
f : α → Seq1 β
g : β → Seq1 γ
a✝ : α
s : Seq α
SS : Seq (Seq1 (Seq1 γ))
a x : γ
s_1 : Seq γ
s_2 : Seq (Seq1 γ)
y : γ
t : Seq γ
⊢ (a, Seq.cons x (append s_1 (Seq.join (Seq.cons (y, t) (append s_2 (Seq.join SS)))))) =
    (a, Seq.cons x (append s_1 (append (Seq.join (Seq.cons (y, t) s_2)) (Seq.join (Seq.map join SS)))))

Next tactic:
simp
instance : CompleteLattice (MorphismProperty C) := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u_1
inst✝ : Category.{?u.105, u_1} D
⊢ CompleteLattice (MorphismProperty C)

Next tactic:
dsimp only [MorphismProperty]
instance : CompleteLattice (MorphismProperty C) := by
  dsimp only [MorphismProperty]
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u_1
inst✝ : Category.{?u.105, u_1} D
⊢ CompleteLattice (⦃X Y : C⦄ → (X ⟶ Y) → Prop)

Next tactic:
infer_instance
lemma top_apply {X Y : C} (f : X ⟶ Y) : (⊤ : MorphismProperty C) f := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u_1
inst✝ : Category.{?u.6658, u_1} D
X Y : C
f : X ⟶ Y
⊢ ⊤ f

Next tactic:
simp only [top_eq]
instance : IsAntisymm (MorphismProperty C) (· ⊆ ·) :=
  ⟨fun P Q => by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u_1
inst✝ : Category.{?u.7423, u_1} D
P Q : MorphismProperty C
⊢ P ⊆ Q → Q ⊆ P → P = Q

Next tactic:
simpa only [subset_iff_le] using le_antisymm
instance : IsRefl (MorphismProperty C) (· ⊆ ·) :=
  ⟨fun P => by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u_1
inst✝ : Category.{?u.7845, u_1} D
P : MorphismProperty C
⊢ P ⊆ P

Next tactic:
simpa only [subset_iff_le] using le_refl P
lemma monotone_map (P Q : MorphismProperty C) (F : C ⥤ D) (h : P ⊆ Q) :
    P.map F ⊆ Q.map F := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u_1
inst✝ : Category.{u_2, u_1} D
P Q : MorphismProperty C
F : C ⥤ D
h : P ⊆ Q
⊢ map P F ⊆ map Q F

Next tactic:
intro X Y f ⟨X', Y', f', hf', ⟨e⟩⟩
lemma monotone_map (P Q : MorphismProperty C) (F : C ⥤ D) (h : P ⊆ Q) :
    P.map F ⊆ Q.map F := by
  intro X Y f ⟨X', Y', f', hf', ⟨e⟩⟩
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u_1
inst✝ : Category.{u_2, u_1} D
P Q : MorphismProperty C
F : C ⥤ D
h : P ⊆ Q
X Y : D
f : X ⟶ Y
X' Y' : C
f' : X' ⟶ Y'
hf' : P f'
e : Arrow.mk (F.map f') ≅ Arrow.mk f
⊢ map Q F f

Next tactic:
exact ⟨X', Y', f', h _ hf', ⟨e⟩⟩
lemma isoClosure_respectsIso (P : MorphismProperty C) :
    RespectsIso P.isoClosure :=
  ⟨fun e f ⟨_, _, f', hf', ⟨iso⟩⟩ =>
    ⟨_, _, f', hf', ⟨Arrow.isoMk (asIso iso.hom.left ≪≫ e.symm)
      (asIso iso.hom.right) (by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u_1
inst✝ : Category.{?u.13579, u_1} D
P : MorphismProperty C
X✝ Y✝ Z✝ : C
e : X✝ ≅ Y✝
f : Y✝ ⟶ Z✝
x✝ : isoClosure P f
w✝¹ w✝ : C
f' : w✝¹ ⟶ w✝
hf' : P f'
iso : Arrow.mk f' ≅ Arrow.mk f
⊢ (asIso iso.hom.left ≪≫ e.symm).hom ≫ (Arrow.mk (e.hom ≫ f)).hom = (Arrow.mk f').hom ≫ (asIso iso.hom.right).hom

Next tactic:
simp
lemma isoClosure_respectsIso (P : MorphismProperty C) :
    RespectsIso P.isoClosure :=
  ⟨fun e f ⟨_, _, f', hf', ⟨iso⟩⟩ =>
    ⟨_, _, f', hf', ⟨Arrow.isoMk (asIso iso.hom.left ≪≫ e.symm)
      (asIso iso.hom.right) (by simp)⟩⟩,
  fun e f ⟨_, _, f', hf', ⟨iso⟩⟩ =>
    ⟨_, _, f', hf', ⟨Arrow.isoMk (asIso iso.hom.left)
      (asIso iso.hom.right ≪≫ e) (by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u_1
inst✝ : Category.{?u.13579, u_1} D
P : MorphismProperty C
X✝ Y✝ Z✝ : C
e : Y✝ ≅ Z✝
f : X✝ ⟶ Y✝
x✝ : isoClosure P f
w✝¹ w✝ : C
f' : w✝¹ ⟶ w✝
hf' : P f'
iso : Arrow.mk f' ≅ Arrow.mk f
⊢ (asIso iso.hom.left).hom ≫ (Arrow.mk (f ≫ e.hom)).hom = (Arrow.mk f').hom ≫ (asIso iso.hom.right ≪≫ e).hom

Next tactic:
simp
lemma monotone_isoClosure (P Q : MorphismProperty C) (h : P ⊆ Q) :
    P.isoClosure ⊆ Q.isoClosure := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u_1
inst✝ : Category.{?u.19500, u_1} D
P Q : MorphismProperty C
h : P ⊆ Q
⊢ isoClosure P ⊆ isoClosure Q

Next tactic:
intro X Y f ⟨X', Y', f', hf', ⟨e⟩⟩
lemma monotone_isoClosure (P Q : MorphismProperty C) (h : P ⊆ Q) :
    P.isoClosure ⊆ Q.isoClosure := by
  intro X Y f ⟨X', Y', f', hf', ⟨e⟩⟩
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u_1
inst✝ : Category.{?u.19500, u_1} D
P Q : MorphismProperty C
h : P ⊆ Q
X Y : C
f : X ⟶ Y
X' Y' : C
f' : X' ⟶ Y'
hf' : P f'
e : Arrow.mk f' ≅ Arrow.mk f
⊢ isoClosure Q f

Next tactic:
exact ⟨X', Y', f', h _ hf', ⟨e⟩⟩
theorem RespectsIso.cancel_left_isIso {P : MorphismProperty C} (hP : RespectsIso P) {X Y Z : C}
    (f : X ⟶ Y) (g : Y ⟶ Z) [IsIso f] : P (f ≫ g) ↔ P g :=
  ⟨fun h => by 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type u_1
inst✝¹ : Category.{?u.24076, u_1} D
P : MorphismProperty C
hP : RespectsIso P
X Y Z : C
f : X ⟶ Y
g : Y ⟶ Z
inst✝ : IsIso f
h : P (f ≫ g)
⊢ P g

Next tactic:
simpa using hP.1 (asIso f).symm (f ≫ g) h
theorem RespectsIso.cancel_right_isIso {P : MorphismProperty C} (hP : RespectsIso P) {X Y Z : C}
    (f : X ⟶ Y) (g : Y ⟶ Z) [IsIso g] : P (f ≫ g) ↔ P f :=
  ⟨fun h => by 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type u_1
inst✝¹ : Category.{?u.25238, u_1} D
P : MorphismProperty C
hP : RespectsIso P
X Y Z : C
f : X ⟶ Y
g : Y ⟶ Z
inst✝ : IsIso g
h : P (f ≫ g)
⊢ P f

Next tactic:
simpa using hP.2 (asIso g).symm (f ≫ g) h
theorem RespectsIso.arrow_iso_iff {P : MorphismProperty C} (hP : RespectsIso P) {f g : Arrow C}
    (e : f ≅ g) : P f.hom ↔ P g.hom := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u_1
inst✝ : Category.{?u.26493, u_1} D
P : MorphismProperty C
hP : RespectsIso P
f g : Arrow C
e : f ≅ g
⊢ P f.hom ↔ P g.hom

Next tactic:
rw [← Arrow.inv_left_hom_right e.hom, hP.cancel_left_isIso, hP.cancel_right_isIso]
theorem RespectsIso.of_respects_arrow_iso (P : MorphismProperty C)
    (hP : ∀ (f g : Arrow C) (_ : f ≅ g) (_ : P f.hom), P g.hom) : RespectsIso P := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u_1
inst✝ : Category.{?u.27858, u_1} D
P : MorphismProperty C
hP : ∀ (f g : Arrow C), (f ≅ g) → P f.hom → P g.hom
⊢ RespectsIso P

Next tactic:
constructor
theorem RespectsIso.of_respects_arrow_iso (P : MorphismProperty C)
    (hP : ∀ (f g : Arrow C) (_ : f ≅ g) (_ : P f.hom), P g.hom) : RespectsIso P := by
  constructor
  · 

Proof state:
case left
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u_1
inst✝ : Category.{?u.27858, u_1} D
P : MorphismProperty C
hP : ∀ (f g : Arrow C), (f ≅ g) → P f.hom → P g.hom
⊢ ∀ {X Y Z : C} (e : X ≅ Y) (f : Y ⟶ Z), P f → P (e.hom ≫ f)

Next tactic:
intro X Y Z e f hf