l3lab/ntp-mathlib huggingface dataset:
theorem stronglyMeasurable_uncurry_of_continuous_of_stronglyMeasurable {α β ι : Type*}
    [TopologicalSpace ι] [MetrizableSpace ι] [MeasurableSpace ι] [SecondCountableTopology ι]
    [OpensMeasurableSpace ι] [TopologicalSpace β] [PseudoMetrizableSpace β] [MeasurableSpace α]
    {u : ι → α → β} (hu_cont : ∀ x, Continuous fun i => u i x) (h : ∀ i, StronglyMeasurable (u i)) :
    StronglyMeasurable (Function.uncurry u) := by
  borelize β
  obtain ⟨t_sf, ht_sf⟩ :
    ∃ t : ℕ → SimpleFunc ι ι, ∀ j x, Tendsto (fun n => u (t n j) x) atTop (𝓝 <| u j x) := by
    have h_str_meas : StronglyMeasurable (id : ι → ι) := stronglyMeasurable_id
    refine' ⟨h_str_meas.approx, fun j x => _⟩
    exact ((hu_cont x).tendsto j).comp (h_str_meas.tendsto_approx j)
  let U (n : ℕ) (p : ι × α) := u (t_sf n p.fst) p.snd
  have h_tendsto : Tendsto U atTop (𝓝 fun p => u p.fst p.snd) := by
    rw [tendsto_pi_nhds]
    exact fun p => ht_sf p.fst p.snd
  refine' stronglyMeasurable_of_tendsto _ (fun n => _) h_tendsto
  have h_str_meas : StronglyMeasurable fun p : (t_sf n).range × α => u (↑p.fst) p.snd := by
    refine' stronglyMeasurable_iff_measurable_separable.2 ⟨_, _⟩
    · have :
        (fun p : ↥(t_sf n).range × α => u (↑p.fst) p.snd) =
          (fun p : α × (t_sf n).range => u (↑p.snd) p.fst) ∘ Prod.swap :=
        rfl
      rw [this, measurable_swap_iff]
      exact measurable_from_prod_countable fun j => (h j).measurable
    · have : IsSeparable (⋃ i : (t_sf n).range, range (u i)) :=
        isSeparable_iUnion fun i => (h i).isSeparable_range
      apply this.mono
      rintro _ ⟨⟨i, x⟩, rfl⟩
      simp only [mem_iUnion, mem_range]
      exact ⟨i, x, rfl⟩
  have :
    (fun p : ι × α => u (t_sf n p.fst) p.snd) =
      (fun p : ↥(t_sf n).range × α => u p.fst p.snd) ∘ fun p : ι × α =>
        (⟨t_sf n p.fst, SimpleFunc.mem_range_self _ _⟩, p.snd) :=
    rfl
  simp_rw [this]
  refine' h_str_meas.comp_measurable (Measurable.prod_mk _ measurable_snd)
  

Proof state:
case intro
α✝ : Type u_1
β✝ : Type u_2
γ : Type u_3
ι✝ : Type u_4
inst✝⁸ : Countable ι✝
α : Type u_5
β : Type u_6
ι : Type u_7
inst✝⁷ : TopologicalSpace ι
inst✝⁶ : MetrizableSpace ι
inst✝⁵ : MeasurableSpace ι
inst✝⁴ : SecondCountableTopology ι
inst✝³ : OpensMeasurableSpace ι
inst✝² : TopologicalSpace β
inst✝¹ : PseudoMetrizableSpace β
inst✝ : MeasurableSpace α
u : ι → α → β
hu_cont : ∀ (x : α), Continuous fun i => u i x
h : ∀ (i : ι), StronglyMeasurable (u i)
this✝¹ : MeasurableSpace β := borel β
this✝ : BorelSpace β
t_sf : ℕ → ι →ₛ ι
ht_sf : ∀ (j : ι) (x : α), Tendsto (fun n => u (↑(t_sf n) j) x) atTop (𝓝 (u j x))
U : ℕ → ι × α → β := fun n p => u (↑(t_sf n) p.1) p.2
h_tendsto : Tendsto U atTop (𝓝 fun p => u p.1 p.2)
n : ℕ
h_str_meas : StronglyMeasurable fun p => u (↑p.1) p.2
this :
  (fun p => u (↑(t_sf n) p.1) p.2) =
    (fun p => u (↑p.1) p.2) ∘ fun p =>
      ({ val := ↑(t_sf n) p.1, property := (_ : ↑(t_sf n) p.1 ∈ SimpleFunc.range (t_sf n)) }, p.2)
⊢ Measurable fun p => { val := ↑(t_sf n) p.1, property := (_ : ↑(t_sf n) p.1 ∈ SimpleFunc.range (t_sf n)) }

Next tactic:
exact ((t_sf n).measurable.comp measurable_fst).subtype_mk
@[simp]
theorem lift_mk {i : ℕ} :
    Cardinal.lift.{v,u} #(Sequence₂ a₀ a₁ a₂ i)
      = #(Sequence₂ (ULift.{v,u} a₀) (ULift.{v,u} a₁) (ULift.{v,u} a₂) i) := by
  

Proof state:
a₀ a₁ a₂ : Type u
i : ℕ
⊢ lift.{v, u} #(Sequence₂ a₀ a₁ a₂ i) = #(Sequence₂ (ULift.{v, u} a₀) (ULift.{v, u} a₁) (ULift.{v, u} a₂) i)

Next tactic:
rcases i with (_ | _ | _ | i)
@[simp]
theorem lift_mk {i : ℕ} :
    Cardinal.lift.{v,u} #(Sequence₂ a₀ a₁ a₂ i)
      = #(Sequence₂ (ULift.{v,u} a₀) (ULift.{v,u} a₁) (ULift.{v,u} a₂) i) := by
  rcases i with (_ | _ | _ | i) <;>
    

Proof state:
case zero
a₀ a₁ a₂ : Type u
⊢ lift.{v, u} #(Sequence₂ a₀ a₁ a₂ Nat.zero) =
    #(Sequence₂ (ULift.{v, u} a₀) (ULift.{v, u} a₁) (ULift.{v, u} a₂) Nat.zero)

Next tactic:
simp only [Sequence₂, mk_uLift, mk_fintype, Nat.cast_zero, lift_zero, Fintype.card_pempty]
@[simp]
theorem lift_mk {i : ℕ} :
    Cardinal.lift.{v,u} #(Sequence₂ a₀ a₁ a₂ i)
      = #(Sequence₂ (ULift.{v,u} a₀) (ULift.{v,u} a₁) (ULift.{v,u} a₂) i) := by
  rcases i with (_ | _ | _ | i) <;>
    

Proof state:
case succ.zero
a₀ a₁ a₂ : Type u
⊢ lift.{v, u} #(Sequence₂ a₀ a₁ a₂ (Nat.succ Nat.zero)) =
    #(Sequence₂ (ULift.{v, u} a₀) (ULift.{v, u} a₁) (ULift.{v, u} a₂) (Nat.succ Nat.zero))

Next tactic:
simp only [Sequence₂, mk_uLift, mk_fintype, Nat.cast_zero, lift_zero, Fintype.card_pempty]
@[simp]
theorem lift_mk {i : ℕ} :
    Cardinal.lift.{v,u} #(Sequence₂ a₀ a₁ a₂ i)
      = #(Sequence₂ (ULift.{v,u} a₀) (ULift.{v,u} a₁) (ULift.{v,u} a₂) i) := by
  rcases i with (_ | _ | _ | i) <;>
    

Proof state:
case succ.succ.zero
a₀ a₁ a₂ : Type u
⊢ lift.{v, u} #(Sequence₂ a₀ a₁ a₂ (Nat.succ (Nat.succ Nat.zero))) =
    #(Sequence₂ (ULift.{v, u} a₀) (ULift.{v, u} a₁) (ULift.{v, u} a₂) (Nat.succ (Nat.succ Nat.zero)))

Next tactic:
simp only [Sequence₂, mk_uLift, mk_fintype, Nat.cast_zero, lift_zero, Fintype.card_pempty]
@[simp]
theorem lift_mk {i : ℕ} :
    Cardinal.lift.{v,u} #(Sequence₂ a₀ a₁ a₂ i)
      = #(Sequence₂ (ULift.{v,u} a₀) (ULift.{v,u} a₁) (ULift.{v,u} a₂) i) := by
  rcases i with (_ | _ | _ | i) <;>
    

Proof state:
case succ.succ.succ
a₀ a₁ a₂ : Type u
i : ℕ
⊢ lift.{v, u} #(Sequence₂ a₀ a₁ a₂ (Nat.succ (Nat.succ (Nat.succ i)))) =
    #(Sequence₂ (ULift.{v, u} a₀) (ULift.{v, u} a₁) (ULift.{v, u} a₂) (Nat.succ (Nat.succ (Nat.succ i))))

Next tactic:
simp only [Sequence₂, mk_uLift, mk_fintype, Nat.cast_zero, lift_zero, Fintype.card_pempty]
@[simp]
theorem sum_card : Cardinal.sum (fun i => #(Sequence₂ a₀ a₁ a₂ i)) = #a₀ + #a₁ + #a₂ := by
  

Proof state:
a₀ a₁ a₂ : Type u
⊢ (sum fun i => #(Sequence₂ a₀ a₁ a₂ i)) = #a₀ + #a₁ + #a₂

Next tactic:
rw [sum_nat_eq_add_sum_succ, sum_nat_eq_add_sum_succ, sum_nat_eq_add_sum_succ]
@[simp]
theorem sum_card : Cardinal.sum (fun i => #(Sequence₂ a₀ a₁ a₂ i)) = #a₀ + #a₁ + #a₂ := by
  rw [sum_nat_eq_add_sum_succ, sum_nat_eq_add_sum_succ, sum_nat_eq_add_sum_succ]
  

Proof state:
a₀ a₁ a₂ : Type u
⊢ #(Sequence₂ a₀ a₁ a₂ 0) +
      (#(Sequence₂ a₀ a₁ a₂ (0 + 1)) +
        (#(Sequence₂ a₀ a₁ a₂ (0 + 1 + 1)) + sum fun i => #(Sequence₂ a₀ a₁ a₂ (i + 1 + 1 + 1)))) =
    #a₀ + #a₁ + #a₂

Next tactic:
simp [add_assoc, Sequence₂]
theorem card_eq_card_functions_add_card_relations :
    L.card =
      (Cardinal.sum fun l => Cardinal.lift.{v} #(L.Functions l)) +
        Cardinal.sum fun l => Cardinal.lift.{u} #(L.Relations l) := by
  

Proof state:
L : Language
L' : Language
⊢ card L = (sum fun l => lift.{v, u} #(Functions L l)) + sum fun l => lift.{u, v} #(Relations L l)

Next tactic:
simp [card, Symbols]
@[simp]
theorem empty_card : Language.empty.card = 0 := by 

Proof state:
L : Language
L' : Language
⊢ card Language.empty = 0

Next tactic:
simp [card_eq_card_functions_add_card_relations]
instance isEmpty_empty : IsEmpty Language.empty.Symbols := by
  

Proof state:
L : Language
L' : Language
⊢ IsEmpty (Symbols Language.empty)

Next tactic:
simp only [Language.Symbols, isEmpty_sum, isEmpty_sigma]
instance isEmpty_empty : IsEmpty Language.empty.Symbols := by
  simp only [Language.Symbols, isEmpty_sum, isEmpty_sigma]
  

Proof state:
L : Language
L' : Language
⊢ (∀ (a : ℕ), IsEmpty (Functions Language.empty a)) ∧ ∀ (a : ℕ), IsEmpty (Relations Language.empty a)

Next tactic:
exact ⟨fun _ => inferInstance, fun _ => inferInstance⟩
@[simp]
theorem card_functions_sum (i : ℕ) :
    #((L.sum L').Functions i)
      = (Cardinal.lift.{u'} #(L.Functions i) + Cardinal.lift.{u} #(L'.Functions i) : Cardinal) := by
  

Proof state:
L : Language
L' : Language
i : ℕ
⊢ #(Functions (Language.sum L L') i) = lift.{u', u} #(Functions L i) + lift.{u, u'} #(Functions L' i)

Next tactic:
simp [Language.sum]
@[simp]
theorem card_relations_sum (i : ℕ) :
    #((L.sum L').Relations i) =
      Cardinal.lift.{v'} #(L.Relations i) + Cardinal.lift.{v} #(L'.Relations i) := by
  

Proof state:
L : Language
L' : Language
i : ℕ
⊢ #(Relations (Language.sum L L') i) = lift.{v', v} #(Relations L i) + lift.{v, v'} #(Relations L' i)

Next tactic:
simp [Language.sum]
@[simp]
theorem card_sum :
    (L.sum L').card = Cardinal.lift.{max u' v'} L.card + Cardinal.lift.{max u v} L'.card := by
  

Proof state:
L : Language
L' : Language
⊢ card (Language.sum L L') = lift.{max u' v', max u v} (card L) + lift.{max u v, max u' v'} (card L')

Next tactic:
simp only [card_eq_card_functions_add_card_relations, card_functions_sum, card_relations_sum,
    sum_add_distrib', lift_add, lift_sum, lift_lift]
@[simp]
theorem card_sum :
    (L.sum L').card = Cardinal.lift.{max u' v'} L.card + Cardinal.lift.{max u v} L'.card := by
  simp only [card_eq_card_functions_add_card_relations, card_functions_sum, card_relations_sum,
    sum_add_distrib', lift_add, lift_sum, lift_lift]
  

Proof state:
L : Language
L' : Language
⊢ ((sum fun i => lift.{max u' v v', u} #(Functions L i)) + sum fun i => lift.{max u v v', u'} #(Functions L' i)) +
      ((sum fun i => lift.{max v' u u', v} #(Relations L i)) + sum fun i => lift.{max v u u', v'} #(Relations L' i)) =
    ((sum fun i => lift.{max v u' v', u} #(Functions L i)) + sum fun i => lift.{max u u' v', v} #(Relations L i)) +
      ((sum fun i => lift.{max v' u v, u'} #(Functions L' i)) + sum fun i => lift.{max u' u v, v'} #(Relations L' i))

Next tactic:
simp only [add_assoc, add_comm (Cardinal.sum fun i => (#(L'.Functions i)).lift)]
@[simp]
theorem card_mk₂ (c f₁ f₂ : Type u) (r₁ r₂ : Type v) :
    (Language.mk₂ c f₁ f₂ r₁ r₂).card =
      Cardinal.lift.{v} #c + Cardinal.lift.{v} #f₁ + Cardinal.lift.{v} #f₂ +
          Cardinal.lift.{u} #r₁ + Cardinal.lift.{u} #r₂ := by
  

Proof state:
L : Language
L' : Language
c f₁ f₂ : Type u
r₁ r₂ : Type v
⊢ card (Language.mk₂ c f₁ f₂ r₁ r₂) =
    lift.{v, u} #c + lift.{v, u} #f₁ + lift.{v, u} #f₂ + lift.{u, v} #r₁ + lift.{u, v} #r₂

Next tactic:
simp [card_eq_card_functions_add_card_relations, add_assoc]
instance funLike : FunLike (M →[L] N) M fun _ => N where
  coe := Hom.toFun
  coe_injective' f g h := by 

Proof state:
L : Language
L' : Language
M : Type w
N : Type w'
inst✝³ : Structure L M
inst✝² : Structure L N
P : Type u_1
inst✝¹ : Structure L P
Q : Type u_2
inst✝ : Structure L Q
f g : M →[L] N
h : f.toFun = g.toFun
⊢ f = g

Next tactic:
cases f
instance funLike : FunLike (M →[L] N) M fun _ => N where
  coe := Hom.toFun
  coe_injective' f g h := by cases f; 

Proof state:
case mk
L : Language
L' : Language
M : Type w
N : Type w'
inst✝³ : Structure L M
inst✝² : Structure L N
P : Type u_1
inst✝¹ : Structure L P
Q : Type u_2
inst✝ : Structure L Q
g : M →[L] N
toFun✝ : M → N
map_fun'✝ : ∀ {n : ℕ} (f : Functions L n) (x : Fin n → M), toFun✝ (funMap f x) = funMap f (toFun✝ ∘ x)
map_rel'✝ : ∀ {n : ℕ} (r : Relations L n) (x : Fin n → M), RelMap r x → RelMap r (toFun✝ ∘ x)
h : (mk toFun✝).toFun = g.toFun
⊢ mk toFun✝ = g

Next tactic:
cases g
instance funLike : FunLike (M →[L] N) M fun _ => N where
  coe := Hom.toFun
  coe_injective' f g h := by cases f; cases g; 

Proof state:
case mk.mk
L : Language
L' : Language
M : Type w
N : Type w'
inst✝³ : Structure L M
inst✝² : Structure L N
P : Type u_1
inst✝¹ : Structure L P
Q : Type u_2
inst✝ : Structure L Q
toFun✝¹ : M → N
map_fun'✝¹ : ∀ {n : ℕ} (f : Functions L n) (x : Fin n → M), toFun✝¹ (funMap f x) = funMap f (toFun✝¹ ∘ x)
map_rel'✝¹ : ∀ {n : ℕ} (r : Relations L n) (x : Fin n → M), RelMap r x → RelMap r (toFun✝¹ ∘ x)
toFun✝ : M → N
map_fun'✝ : ∀ {n : ℕ} (f : Functions L n) (x : Fin n → M), toFun✝ (funMap f x) = funMap f (toFun✝ ∘ x)
map_rel'✝ : ∀ {n : ℕ} (r : Relations L n) (x : Fin n → M), RelMap r x → RelMap r (toFun✝ ∘ x)
h : (mk toFun✝¹).toFun = (mk toFun✝).toFun
⊢ mk toFun✝¹ = mk toFun✝

Next tactic:
cases h
instance funLike : FunLike (M →[L] N) M fun _ => N where
  coe := Hom.toFun
  coe_injective' f g h := by cases f; cases g; cases h; 

Proof state:
case mk.mk.refl
L : Language
L' : Language
M : Type w
N : Type w'
inst✝³ : Structure L M
inst✝² : Structure L N
P : Type u_1
inst✝¹ : Structure L P
Q : Type u_2
inst✝ : Structure L Q
toFun✝ : M → N
map_fun'✝¹ : ∀ {n : ℕ} (f : Functions L n) (x : Fin n → M), toFun✝ (funMap f x) = funMap f (toFun✝ ∘ x)
map_rel'✝¹ : ∀ {n : ℕ} (r : Relations L n) (x : Fin n → M), RelMap r x → RelMap r (toFun✝ ∘ x)
map_fun'✝ : ∀ {n : ℕ} (f : Functions L n) (x : Fin n → M), toFun✝ (funMap f x) = funMap f (toFun✝ ∘ x)
map_rel'✝ : ∀ {n : ℕ} (r : Relations L n) (x : Fin n → M), RelMap r x → RelMap r (toFun✝ ∘ x)
⊢ mk toFun✝ = mk toFun✝

Next tactic:
rfl
/-- Composition of first-order homomorphisms. -/
@[trans]
def comp (hnp : N →[L] P) (hmn : M →[L] N) : M →[L] P where
  toFun := hnp ∘ hmn
  -- Porting note: should be done by autoparam?
  map_fun' _ _ := by 

Proof state:
L : Language
L' : Language
M : Type w
N : Type w'
inst✝³ : Structure L M
inst✝² : Structure L N
P : Type u_1
inst✝¹ : Structure L P
Q : Type u_2
inst✝ : Structure L Q
hnp : N →[L] P
hmn : M →[L] N
n✝ : ℕ
x✝¹ : Functions L n✝
x✝ : Fin n✝ → M
⊢ (⇑hnp ∘ ⇑hmn) (funMap x✝¹ x✝) = funMap x✝¹ ((⇑hnp ∘ ⇑hmn) ∘ x✝)

Next tactic:
simp
/-- Composition of first-order homomorphisms. -/
@[trans]
def comp (hnp : N →[L] P) (hmn : M →[L] N) : M →[L] P where
  toFun := hnp ∘ hmn
  -- Porting note: should be done by autoparam?
  map_fun' _ _ := by simp; 

Proof state:
L : Language
L' : Language
M : Type w
N : Type w'
inst✝³ : Structure L M
inst✝² : Structure L N
P : Type u_1
inst✝¹ : Structure L P
Q : Type u_2
inst✝ : Structure L Q
hnp : N →[L] P
hmn : M →[L] N
n✝ : ℕ
x✝¹ : Functions L n✝
x✝ : Fin n✝ → M
⊢ funMap x✝¹ (⇑hnp ∘ ⇑hmn ∘ x✝) = funMap x✝¹ ((⇑hnp ∘ ⇑hmn) ∘ x✝)

Next tactic:
rfl
instance embeddingLike : EmbeddingLike (M ↪[L] N) M N where
  coe f := f.toFun
  injective' f := f.toEmbedding.injective
  coe_injective' f g h := by
    

Proof state:
L : Language
L' : Language
M : Type w
N : Type w'
inst✝³ : Structure L M
inst✝² : Structure L N
P : Type u_1
inst✝¹ : Structure L P
Q : Type u_2
inst✝ : Structure L Q
f g : M ↪[L] N
h : (fun f => f.toFun) f = (fun f => f.toFun) g
⊢ f = g

Next tactic:
cases f
instance embeddingLike : EmbeddingLike (M ↪[L] N) M N where
  coe f := f.toFun
  injective' f := f.toEmbedding.injective
  coe_injective' f g h := by
    cases f
    

Proof state:
case mk
L : Language
L' : Language
M : Type w
N : Type w'
inst✝³ : Structure L M
inst✝² : Structure L N
P : Type u_1
inst✝¹ : Structure L P
Q : Type u_2
inst✝ : Structure L Q
g : M ↪[L] N
toEmbedding✝ : M ↪ N
map_fun'✝ :
  ∀ {n : ℕ} (f : Functions L n) (x : Fin n → M),
    Function.Embedding.toFun toEmbedding✝ (funMap f x) = funMap f (toEmbedding✝.toFun ∘ x)
map_rel'✝ : ∀ {n : ℕ} (r : Relations L n) (x : Fin n → M), RelMap r (toEmbedding✝.toFun ∘ x) ↔ RelMap r x
h : (fun f => f.toFun) (mk toEmbedding✝) = (fun f => f.toFun) g
⊢ mk toEmbedding✝ = g

Next tactic:
cases g
instance embeddingLike : EmbeddingLike (M ↪[L] N) M N where
  coe f := f.toFun
  injective' f := f.toEmbedding.injective
  coe_injective' f g h := by
    cases f
    cases g
    

Proof state:
case mk.mk
L : Language
L' : Language
M : Type w
N : Type w'
inst✝³ : Structure L M
inst✝² : Structure L N
P : Type u_1
inst✝¹ : Structure L P
Q : Type u_2
inst✝ : Structure L Q
toEmbedding✝¹ : M ↪ N
map_fun'✝¹ :
  ∀ {n : ℕ} (f : Functions L n) (x : Fin n → M),
    Function.Embedding.toFun toEmbedding✝¹ (funMap f x) = funMap f (toEmbedding✝¹.toFun ∘ x)
map_rel'✝¹ : ∀ {n : ℕ} (r : Relations L n) (x : Fin n → M), RelMap r (toEmbedding✝¹.toFun ∘ x) ↔ RelMap r x
toEmbedding✝ : M ↪ N
map_fun'✝ :
  ∀ {n : ℕ} (f : Functions L n) (x : Fin n → M),
    Function.Embedding.toFun toEmbedding✝ (funMap f x) = funMap f (toEmbedding✝.toFun ∘ x)
map_rel'✝ : ∀ {n : ℕ} (r : Relations L n) (x : Fin n → M), RelMap r (toEmbedding✝.toFun ∘ x) ↔ RelMap r x
h : (fun f => f.toFun) (mk toEmbedding✝¹) = (fun f => f.toFun) (mk toEmbedding✝)
⊢ mk toEmbedding✝¹ = mk toEmbedding✝

Next tactic:
congr
instance embeddingLike : EmbeddingLike (M ↪[L] N) M N where
  coe f := f.toFun
  injective' f := f.toEmbedding.injective
  coe_injective' f g h := by
    cases f
    cases g
    congr
    

Proof state:
case mk.mk.e_toEmbedding
L : Language
L' : Language
M : Type w
N : Type w'
inst✝³ : Structure L M
inst✝² : Structure L N
P : Type u_1
inst✝¹ : Structure L P
Q : Type u_2
inst✝ : Structure L Q
toEmbedding✝¹ : M ↪ N
map_fun'✝¹ :
  ∀ {n : ℕ} (f : Functions L n) (x : Fin n → M),
    Function.Embedding.toFun toEmbedding✝¹ (funMap f x) = funMap f (toEmbedding✝¹.toFun ∘ x)
map_rel'✝¹ : ∀ {n : ℕ} (r : Relations L n) (x : Fin n → M), RelMap r (toEmbedding✝¹.toFun ∘ x) ↔ RelMap r x
toEmbedding✝ : M ↪ N
map_fun'✝ :
  ∀ {n : ℕ} (f : Functions L n) (x : Fin n → M),
    Function.Embedding.toFun toEmbedding✝ (funMap f x) = funMap f (toEmbedding✝.toFun ∘ x)
map_rel'✝ : ∀ {n : ℕ} (r : Relations L n) (x : Fin n → M), RelMap r (toEmbedding✝.toFun ∘ x) ↔ RelMap r x
h : (fun f => f.toFun) (mk toEmbedding✝¹) = (fun f => f.toFun) (mk toEmbedding✝)
⊢ toEmbedding✝¹ = toEmbedding✝

Next tactic:
ext x
instance embeddingLike : EmbeddingLike (M ↪[L] N) M N where
  coe f := f.toFun
  injective' f := f.toEmbedding.injective
  coe_injective' f g h := by
    cases f
    cases g
    congr
    ext x
    

Proof state:
case mk.mk.e_toEmbedding.h
L : Language
L' : Language
M : Type w
N : Type w'
inst✝³ : Structure L M
inst✝² : Structure L N
P : Type u_1
inst✝¹ : Structure L P
Q : Type u_2
inst✝ : Structure L Q
toEmbedding✝¹ : M ↪ N
map_fun'✝¹ :
  ∀ {n : ℕ} (f : Functions L n) (x : Fin n → M),
    Function.Embedding.toFun toEmbedding✝¹ (funMap f x) = funMap f (toEmbedding✝¹.toFun ∘ x)
map_rel'✝¹ : ∀ {n : ℕ} (r : Relations L n) (x : Fin n → M), RelMap r (toEmbedding✝¹.toFun ∘ x) ↔ RelMap r x
toEmbedding✝ : M ↪ N
map_fun'✝ :
  ∀ {n : ℕ} (f : Functions L n) (x : Fin n → M),
    Function.Embedding.toFun toEmbedding✝ (funMap f x) = funMap f (toEmbedding✝.toFun ∘ x)
map_rel'✝ : ∀ {n : ℕ} (r : Relations L n) (x : Fin n → M), RelMap r (toEmbedding✝.toFun ∘ x) ↔ RelMap r x
h : (fun f => f.toFun) (mk toEmbedding✝¹) = (fun f => f.toFun) (mk toEmbedding✝)
x : M
⊢ toEmbedding✝¹ x = toEmbedding✝ x

Next tactic:
exact Function.funext_iff.1 h x
theorem coe_injective : @Function.Injective (M ↪[L] N) (M → N) (↑)
  | f, g, h => by
    

Proof state:
L : Language
L' : Language
M : Type w
N : Type w'
inst✝³ : Structure L M
inst✝² : Structure L N
P : Type u_1
inst✝¹ : Structure L P
Q : Type u_2
inst✝ : Structure L Q
f g : M ↪[L] N
h : ⇑f = ⇑g
⊢ f = g

Next tactic:
cases f
theorem coe_injective : @Function.Injective (M ↪[L] N) (M → N) (↑)
  | f, g, h => by
    cases f
    

Proof state:
case mk
L : Language
L' : Language
M : Type w
N : Type w'
inst✝³ : Structure L M
inst✝² : Structure L N
P : Type u_1
inst✝¹ : Structure L P
Q : Type u_2
inst✝ : Structure L Q
g : M ↪[L] N
toEmbedding✝ : M ↪ N
map_fun'✝ :
  ∀ {n : ℕ} (f : Functions L n) (x : Fin n → M),
    Function.Embedding.toFun toEmbedding✝ (funMap f x) = funMap f (toEmbedding✝.toFun ∘ x)
map_rel'✝ : ∀ {n : ℕ} (r : Relations L n) (x : Fin n → M), RelMap r (toEmbedding✝.toFun ∘ x) ↔ RelMap r x
h : ⇑(mk toEmbedding✝) = ⇑g
⊢ mk toEmbedding✝ = g

Next tactic:
cases g
theorem coe_injective : @Function.Injective (M ↪[L] N) (M → N) (↑)
  | f, g, h => by
    cases f
    cases g
    

Proof state:
case mk.mk
L : Language
L' : Language
M : Type w
N : Type w'
inst✝³ : Structure L M
inst✝² : Structure L N
P : Type u_1
inst✝¹ : Structure L P
Q : Type u_2
inst✝ : Structure L Q
toEmbedding✝¹ : M ↪ N
map_fun'✝¹ :
  ∀ {n : ℕ} (f : Functions L n) (x : Fin n → M),
    Function.Embedding.toFun toEmbedding✝¹ (funMap f x) = funMap f (toEmbedding✝¹.toFun ∘ x)
map_rel'✝¹ : ∀ {n : ℕ} (r : Relations L n) (x : Fin n → M), RelMap r (toEmbedding✝¹.toFun ∘ x) ↔ RelMap r x
toEmbedding✝ : M ↪ N
map_fun'✝ :
  ∀ {n : ℕ} (f : Functions L n) (x : Fin n → M),
    Function.Embedding.toFun toEmbedding✝ (funMap f x) = funMap f (toEmbedding✝.toFun ∘ x)
map_rel'✝ : ∀ {n : ℕ} (r : Relations L n) (x : Fin n → M), RelMap r (toEmbedding✝.toFun ∘ x) ↔ RelMap r x
h : ⇑(mk toEmbedding✝¹) = ⇑(mk toEmbedding✝)
⊢ mk toEmbedding✝¹ = mk toEmbedding✝

Next tactic:
congr
theorem coe_injective : @Function.Injective (M ↪[L] N) (M → N) (↑)
  | f, g, h => by
    cases f
    cases g
    congr
    

Proof state:
case mk.mk.e_toEmbedding
L : Language
L' : Language
M : Type w
N : Type w'
inst✝³ : Structure L M
inst✝² : Structure L N
P : Type u_1
inst✝¹ : Structure L P
Q : Type u_2
inst✝ : Structure L Q
toEmbedding✝¹ : M ↪ N
map_fun'✝¹ :
  ∀ {n : ℕ} (f : Functions L n) (x : Fin n → M),
    Function.Embedding.toFun toEmbedding✝¹ (funMap f x) = funMap f (toEmbedding✝¹.toFun ∘ x)
map_rel'✝¹ : ∀ {n : ℕ} (r : Relations L n) (x : Fin n → M), RelMap r (toEmbedding✝¹.toFun ∘ x) ↔ RelMap r x
toEmbedding✝ : M ↪ N
map_fun'✝ :
  ∀ {n : ℕ} (f : Functions L n) (x : Fin n → M),
    Function.Embedding.toFun toEmbedding✝ (funMap f x) = funMap f (toEmbedding✝.toFun ∘ x)
map_rel'✝ : ∀ {n : ℕ} (r : Relations L n) (x : Fin n → M), RelMap r (toEmbedding✝.toFun ∘ x) ↔ RelMap r x
h : ⇑(mk toEmbedding✝¹) = ⇑(mk toEmbedding✝)
⊢ toEmbedding✝¹ = toEmbedding✝

Next tactic:
ext x
theorem coe_injective : @Function.Injective (M ↪[L] N) (M → N) (↑)
  | f, g, h => by
    cases f
    cases g
    congr
    ext x
    

Proof state:
case mk.mk.e_toEmbedding.h
L : Language
L' : Language
M : Type w
N : Type w'
inst✝³ : Structure L M
inst✝² : Structure L N
P : Type u_1
inst✝¹ : Structure L P
Q : Type u_2
inst✝ : Structure L Q
toEmbedding✝¹ : M ↪ N
map_fun'✝¹ :
  ∀ {n : ℕ} (f : Functions L n) (x : Fin n → M),
    Function.Embedding.toFun toEmbedding✝¹ (funMap f x) = funMap f (toEmbedding✝¹.toFun ∘ x)
map_rel'✝¹ : ∀ {n : ℕ} (r : Relations L n) (x : Fin n → M), RelMap r (toEmbedding✝¹.toFun ∘ x) ↔ RelMap r x
toEmbedding✝ : M ↪ N
map_fun'✝ :
  ∀ {n : ℕ} (f : Functions L n) (x : Fin n → M),
    Function.Embedding.toFun toEmbedding✝ (funMap f x) = funMap f (toEmbedding✝.toFun ∘ x)
map_rel'✝ : ∀ {n : ℕ} (r : Relations L n) (x : Fin n → M), RelMap r (toEmbedding✝.toFun ∘ x) ↔ RelMap r x
h : ⇑(mk toEmbedding✝¹) = ⇑(mk toEmbedding✝)
x : M
⊢ toEmbedding✝¹ x = toEmbedding✝ x

Next tactic:
exact Function.funext_iff.1 h x
@[simp]
theorem ofInjective_toHom [L.IsAlgebraic] {f : M →[L] N} (hf : Function.Injective f) :
    (ofInjective hf).toHom = f := by
  

Proof state:
L : Language
L' : Language
M : Type w
N : Type w'
inst✝⁴ : Structure L M
inst✝³ : Structure L N
P : Type u_1
inst✝² : Structure L P
Q : Type u_2
inst✝¹ : Structure L Q
inst✝ : IsAlgebraic L
f : M →[L] N
hf : Function.Injective ⇑f
⊢ toHom (ofInjective hf) = f

Next tactic:
ext
@[simp]
theorem ofInjective_toHom [L.IsAlgebraic] {f : M →[L] N} (hf : Function.Injective f) :
    (ofInjective hf).toHom = f := by
  ext; 

Proof state:
case h
L : Language
L' : Language
M : Type w
N : Type w'
inst✝⁴ : Structure L M
inst✝³ : Structure L N
P : Type u_1
inst✝² : Structure L P
Q : Type u_2
inst✝¹ : Structure L Q
inst✝ : IsAlgebraic L
f : M →[L] N
hf : Function.Injective ⇑f
x✝ : M
⊢ (toHom (ofInjective hf)) x✝ = f x✝

Next tactic:
simp
/-- Composition of first-order embeddings. -/
@[trans]
def comp (hnp : N ↪[L] P) (hmn : M ↪[L] N) : M ↪[L] P where
  toFun := hnp ∘ hmn
  inj' := hnp.injective.comp hmn.injective
  -- Porting note: should be done by autoparam?
  map_fun' := by 

Proof state:
L : Language
L' : Language
M : Type w
N : Type w'
inst✝³ : Structure L M
inst✝² : Structure L N
P : Type u_1
inst✝¹ : Structure L P
Q : Type u_2
inst✝ : Structure L Q
hnp : N ↪[L] P
hmn : M ↪[L] N
⊢ ∀ {n : ℕ} (f : Functions L n) (x : Fin n → M),
    Function.Embedding.toFun { toFun := ⇑hnp ∘ ⇑hmn, inj' := (_ : Function.Injective (⇑hnp ∘ ⇑hmn)) } (funMap f x) =
      funMap f ({ toFun := ⇑hnp ∘ ⇑hmn, inj' := (_ : Function.Injective (⇑hnp ∘ ⇑hmn)) }.toFun ∘ x)

Next tactic:
intros
/-- Composition of first-order embeddings. -/
@[trans]
def comp (hnp : N ↪[L] P) (hmn : M ↪[L] N) : M ↪[L] P where
  toFun := hnp ∘ hmn
  inj' := hnp.injective.comp hmn.injective
  -- Porting note: should be done by autoparam?
  map_fun' := by intros; 

Proof state:
L : Language
L' : Language
M : Type w
N : Type w'
inst✝³ : Structure L M
inst✝² : Structure L N
P : Type u_1
inst✝¹ : Structure L P
Q : Type u_2
inst✝ : Structure L Q
hnp : N ↪[L] P
hmn : M ↪[L] N
n✝ : ℕ
f✝ : Functions L n✝
x✝ : Fin n✝ → M
⊢ Function.Embedding.toFun { toFun := ⇑hnp ∘ ⇑hmn, inj' := (_ : Function.Injective (⇑hnp ∘ ⇑hmn)) } (funMap f✝ x✝) =
    funMap f✝ ({ toFun := ⇑hnp ∘ ⇑hmn, inj' := (_ : Function.Injective (⇑hnp ∘ ⇑hmn)) }.toFun ∘ x✝)

Next tactic:
simp only [Function.comp_apply, map_fun]