l3lab/ntp-mathlib huggingface dataset:
/-- The `Kleisli` category of a `Control.Monad` is equivalent to the `Kleisli` category of its
category-theoretic version, provided the monad is lawful.
-/
@[simps]
def eq : KleisliCat m ≌ Kleisli (ofTypeMonad m) where
  functor :=
    { obj := fun X => X
      map := fun f => f
      map_id := fun X => rfl
      map_comp := fun f g => by
        --unfold_projs
        funext t
        -- Porting note: missing tactic `unfold_projs`, using `change` instead.
        change _ = joinM (g <$> (f t))
        simp only [joinM, seq_bind_eq, Function.comp.left_id]
        rfl }
  inverse :=
    { obj := fun X => X
      map := fun f => f
      map_id := fun X => rfl
      map_comp := fun f g => by
        --unfold_projs
        --Porting note: Need these instances for some lemmas below.
        --Should they be added as actual instances elsewhere?
        letI : _root_.Monad (ofTypeMonad m).obj :=
          show _root_.Monad m from inferInstance
        letI : LawfulMonad (ofTypeMonad m).obj :=
          show LawfulMonad m from inferInstance
        funext t
        dsimp
        -- Porting note: missing tactic `unfold_projs`, using `change` instead.
        change joinM (g <$> (f t)) = _
        simp only [joinM, seq_bind_eq, Function.comp.left_id]
        rfl }
  unitIso := by
    refine' NatIso.ofComponents (fun X => Iso.refl X) fun f => _
    

Proof state:
m : Type u → Type u
inst✝¹ : _root_.Monad m
inst✝ : LawfulMonad m
X✝ Y✝ : KleisliCat m
f : X✝ ⟶ Y✝
⊢ (𝟭 (KleisliCat m)).map f ≫ ((fun X => Iso.refl X) Y✝).hom =
    ((fun X => Iso.refl X) X✝).hom ≫
      (Functor.mk { obj := fun X => X, map := fun {X Y} f => f } ⋙
            Functor.mk { obj := fun X => X, map := fun {X Y} f => f }).map
        f

Next tactic:
change f >=> pure = pure >=> f
/-- The `Kleisli` category of a `Control.Monad` is equivalent to the `Kleisli` category of its
category-theoretic version, provided the monad is lawful.
-/
@[simps]
def eq : KleisliCat m ≌ Kleisli (ofTypeMonad m) where
  functor :=
    { obj := fun X => X
      map := fun f => f
      map_id := fun X => rfl
      map_comp := fun f g => by
        --unfold_projs
        funext t
        -- Porting note: missing tactic `unfold_projs`, using `change` instead.
        change _ = joinM (g <$> (f t))
        simp only [joinM, seq_bind_eq, Function.comp.left_id]
        rfl }
  inverse :=
    { obj := fun X => X
      map := fun f => f
      map_id := fun X => rfl
      map_comp := fun f g => by
        --unfold_projs
        --Porting note: Need these instances for some lemmas below.
        --Should they be added as actual instances elsewhere?
        letI : _root_.Monad (ofTypeMonad m).obj :=
          show _root_.Monad m from inferInstance
        letI : LawfulMonad (ofTypeMonad m).obj :=
          show LawfulMonad m from inferInstance
        funext t
        dsimp
        -- Porting note: missing tactic `unfold_projs`, using `change` instead.
        change joinM (g <$> (f t)) = _
        simp only [joinM, seq_bind_eq, Function.comp.left_id]
        rfl }
  unitIso := by
    refine' NatIso.ofComponents (fun X => Iso.refl X) fun f => _
    change f >=> pure = pure >=> f
    

Proof state:
m : Type u → Type u
inst✝¹ : _root_.Monad m
inst✝ : LawfulMonad m
X✝ Y✝ : KleisliCat m
f : X✝ ⟶ Y✝
⊢ f >=> pure = pure >=> f

Next tactic:
simp [functor_norm]
@[simp]
theorem realize_relabel {t : L.Term α} {g : α → β} {v : β → M} :
    (t.relabel g).realize v = t.realize (v ∘ g) := by
  

Proof state:
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
t : Term L α
g : α → β
v : β → M
⊢ realize v (relabel g t) = realize (v ∘ g) t

Next tactic:
induction' t with _ n f ts ih
@[simp]
theorem realize_relabel {t : L.Term α} {g : α → β} {v : β → M} :
    (t.relabel g).realize v = t.realize (v ∘ g) := by
  induction' t with _ n f ts ih
  · 

Proof state:
case var
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
g : α → β
v : β → M
_a✝ : α
⊢ realize v (relabel g (var _a✝)) = realize (v ∘ g) (var _a✝)

Next tactic:
rfl
@[simp]
theorem realize_relabel {t : L.Term α} {g : α → β} {v : β → M} :
    (t.relabel g).realize v = t.realize (v ∘ g) := by
  induction' t with _ n f ts ih
  · rfl
  · 

Proof state:
case func
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
g : α → β
v : β → M
n : ℕ
f : Functions L n
ts : Fin n → Term L α
ih : ∀ (a : Fin n), realize v (relabel g (ts a)) = realize (v ∘ g) (ts a)
⊢ realize v (relabel g (func f ts)) = realize (v ∘ g) (func f ts)

Next tactic:
simp [ih]
@[simp]
theorem realize_functions_apply₁ {f : L.Functions 1} {t : L.Term α} {v : α → M} :
    (f.apply₁ t).realize v = funMap f ![t.realize v] := by
  

Proof state:
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
f : Functions L 1
t : Term L α
v : α → M
⊢ realize v (Functions.apply₁ f t) = funMap f ![realize v t]

Next tactic:
rw [Functions.apply₁, Term.realize]
@[simp]
theorem realize_functions_apply₁ {f : L.Functions 1} {t : L.Term α} {v : α → M} :
    (f.apply₁ t).realize v = funMap f ![t.realize v] := by
  rw [Functions.apply₁, Term.realize]
  

Proof state:
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
f : Functions L 1
t : Term L α
v : α → M
⊢ (funMap f fun i => realize v (Matrix.vecCons t ![] i)) = funMap f ![realize v t]

Next tactic:
refine' congr rfl (funext fun i => _)
@[simp]
theorem realize_functions_apply₁ {f : L.Functions 1} {t : L.Term α} {v : α → M} :
    (f.apply₁ t).realize v = funMap f ![t.realize v] := by
  rw [Functions.apply₁, Term.realize]
  refine' congr rfl (funext fun i => _)
  

Proof state:
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
f : Functions L 1
t : Term L α
v : α → M
i : Fin 1
⊢ realize v (Matrix.vecCons t ![] i) = Matrix.vecCons (realize v t) ![] i

Next tactic:
simp only [Matrix.cons_val_fin_one]
@[simp]
theorem realize_functions_apply₂ {f : L.Functions 2} {t₁ t₂ : L.Term α} {v : α → M} :
    (f.apply₂ t₁ t₂).realize v = funMap f ![t₁.realize v, t₂.realize v] := by
  

Proof state:
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
f : Functions L 2
t₁ t₂ : Term L α
v : α → M
⊢ realize v (Functions.apply₂ f t₁ t₂) = funMap f ![realize v t₁, realize v t₂]

Next tactic:
rw [Functions.apply₂, Term.realize]
@[simp]
theorem realize_functions_apply₂ {f : L.Functions 2} {t₁ t₂ : L.Term α} {v : α → M} :
    (f.apply₂ t₁ t₂).realize v = funMap f ![t₁.realize v, t₂.realize v] := by
  rw [Functions.apply₂, Term.realize]
  

Proof state:
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
f : Functions L 2
t₁ t₂ : Term L α
v : α → M
⊢ (funMap f fun i => realize v (Matrix.vecCons t₁ ![t₂] i)) = funMap f ![realize v t₁, realize v t₂]

Next tactic:
refine' congr rfl (funext (Fin.cases _ _))
@[simp]
theorem realize_functions_apply₂ {f : L.Functions 2} {t₁ t₂ : L.Term α} {v : α → M} :
    (f.apply₂ t₁ t₂).realize v = funMap f ![t₁.realize v, t₂.realize v] := by
  rw [Functions.apply₂, Term.realize]
  refine' congr rfl (funext (Fin.cases _ _))
  · 

Proof state:
case refine'_1
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
f : Functions L 2
t₁ t₂ : Term L α
v : α → M
⊢ realize v (Matrix.vecCons t₁ ![t₂] 0) = Matrix.vecCons (realize v t₁) ![realize v t₂] 0

Next tactic:
simp only [Matrix.cons_val_zero]
@[simp]
theorem realize_functions_apply₂ {f : L.Functions 2} {t₁ t₂ : L.Term α} {v : α → M} :
    (f.apply₂ t₁ t₂).realize v = funMap f ![t₁.realize v, t₂.realize v] := by
  rw [Functions.apply₂, Term.realize]
  refine' congr rfl (funext (Fin.cases _ _))
  · simp only [Matrix.cons_val_zero]
  · 

Proof state:
case refine'_2
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
f : Functions L 2
t₁ t₂ : Term L α
v : α → M
⊢ ∀ (i : Fin 1), realize v (Matrix.vecCons t₁ ![t₂] (succ i)) = Matrix.vecCons (realize v t₁) ![realize v t₂] (succ i)

Next tactic:
simp only [Matrix.cons_val_succ, Matrix.cons_val_fin_one, forall_const]
@[simp]
theorem realize_subst {t : L.Term α} {tf : α → L.Term β} {v : β → M} :
    (t.subst tf).realize v = t.realize fun a => (tf a).realize v := by
  

Proof state:
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
t : Term L α
tf : α → Term L β
v : β → M
⊢ realize v (subst t tf) = realize (fun a => realize v (tf a)) t

Next tactic:
induction' t with _ _ _ _ ih
@[simp]
theorem realize_subst {t : L.Term α} {tf : α → L.Term β} {v : β → M} :
    (t.subst tf).realize v = t.realize fun a => (tf a).realize v := by
  induction' t with _ _ _ _ ih
  · 

Proof state:
case var
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
tf : α → Term L β
v : β → M
_a✝ : α
⊢ realize v (subst (var _a✝) tf) = realize (fun a => realize v (tf a)) (var _a✝)

Next tactic:
rfl
@[simp]
theorem realize_subst {t : L.Term α} {tf : α → L.Term β} {v : β → M} :
    (t.subst tf).realize v = t.realize fun a => (tf a).realize v := by
  induction' t with _ _ _ _ ih
  · rfl
  · 

Proof state:
case func
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
tf : α → Term L β
v : β → M
l✝ : ℕ
_f✝ : Functions L l✝
_ts✝ : Fin l✝ → Term L α
ih : ∀ (a : Fin l✝), realize v (subst (_ts✝ a) tf) = realize (fun a => realize v (tf a)) (_ts✝ a)
⊢ realize v (subst (func _f✝ _ts✝) tf) = realize (fun a => realize v (tf a)) (func _f✝ _ts✝)

Next tactic:
simp [ih]
@[simp]
theorem realize_restrictVar [DecidableEq α] {t : L.Term α} {s : Set α} (h : ↑t.varFinset ⊆ s)
    {v : α → M} : (t.restrictVar (Set.inclusion h)).realize (v ∘ (↑)) = t.realize v := by
  

Proof state:
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝³ : Structure L M
inst✝² : Structure L N
inst✝¹ : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
inst✝ : DecidableEq α
t : Term L α
s : Set α
h : ↑(varFinset t) ⊆ s
v : α → M
⊢ realize (v ∘ Subtype.val) (restrictVar t (Set.inclusion h)) = realize v t

Next tactic:
induction' t with _ _ _ _ ih
@[simp]
theorem realize_restrictVar [DecidableEq α] {t : L.Term α} {s : Set α} (h : ↑t.varFinset ⊆ s)
    {v : α → M} : (t.restrictVar (Set.inclusion h)).realize (v ∘ (↑)) = t.realize v := by
  induction' t with _ _ _ _ ih
  · 

Proof state:
case var
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝³ : Structure L M
inst✝² : Structure L N
inst✝¹ : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
inst✝ : DecidableEq α
s : Set α
v : α → M
_a✝ : α
h : ↑(varFinset (var _a✝)) ⊆ s
⊢ realize (v ∘ Subtype.val) (restrictVar (var _a✝) (Set.inclusion h)) = realize v (var _a✝)

Next tactic:
rfl
@[simp]
theorem realize_restrictVar [DecidableEq α] {t : L.Term α} {s : Set α} (h : ↑t.varFinset ⊆ s)
    {v : α → M} : (t.restrictVar (Set.inclusion h)).realize (v ∘ (↑)) = t.realize v := by
  induction' t with _ _ _ _ ih
  · rfl
  · 

Proof state:
case func
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝³ : Structure L M
inst✝² : Structure L N
inst✝¹ : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
inst✝ : DecidableEq α
s : Set α
v : α → M
l✝ : ℕ
_f✝ : Functions L l✝
_ts✝ : Fin l✝ → Term L α
ih :
  ∀ (a : Fin l✝) (h : ↑(varFinset (_ts✝ a)) ⊆ s),
    realize (v ∘ Subtype.val) (restrictVar (_ts✝ a) (Set.inclusion h)) = realize v (_ts✝ a)
h : ↑(varFinset (func _f✝ _ts✝)) ⊆ s
⊢ realize (v ∘ Subtype.val) (restrictVar (func _f✝ _ts✝) (Set.inclusion h)) = realize v (func _f✝ _ts✝)

Next tactic:
simp_rw [varFinset, Finset.coe_biUnion, Set.iUnion_subset_iff] at h
@[simp]
theorem realize_restrictVar [DecidableEq α] {t : L.Term α} {s : Set α} (h : ↑t.varFinset ⊆ s)
    {v : α → M} : (t.restrictVar (Set.inclusion h)).realize (v ∘ (↑)) = t.realize v := by
  induction' t with _ _ _ _ ih
  · rfl
  · simp_rw [varFinset, Finset.coe_biUnion, Set.iUnion_subset_iff] at h
    

Proof state:
case func
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝³ : Structure L M
inst✝² : Structure L N
inst✝¹ : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
inst✝ : DecidableEq α
s : Set α
v : α → M
l✝ : ℕ
_f✝ : Functions L l✝
_ts✝ : Fin l✝ → Term L α
ih :
  ∀ (a : Fin l✝) (h : ↑(varFinset (_ts✝ a)) ⊆ s),
    realize (v ∘ Subtype.val) (restrictVar (_ts✝ a) (Set.inclusion h)) = realize v (_ts✝ a)
h✝ : ↑(Finset.biUnion Finset.univ fun i => varFinset (_ts✝ i)) ⊆ s
h : ∀ i ∈ ↑Finset.univ, ↑(varFinset (_ts✝ i)) ⊆ s
⊢ realize (v ∘ Subtype.val) (restrictVar (func _f✝ _ts✝) (Set.inclusion h✝)) = realize v (func _f✝ _ts✝)

Next tactic:
exact congr rfl (funext fun i => ih i (h i (Finset.mem_univ i)))
@[simp]
theorem realize_restrictVarLeft [DecidableEq α] {γ : Type*} {t : L.Term (Sum α γ)} {s : Set α}
    (h : ↑t.varFinsetLeft ⊆ s) {v : α → M} {xs : γ → M} :
    (t.restrictVarLeft (Set.inclusion h)).realize (Sum.elim (v ∘ (↑)) xs) =
      t.realize (Sum.elim v xs) := by
  

Proof state:
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝³ : Structure L M
inst✝² : Structure L N
inst✝¹ : Structure L P
α : Type u'
β : Type v'
γ✝ : Type u_3
inst✝ : DecidableEq α
γ : Type u_4
t : Term L (α ⊕ γ)
s : Set α
h : ↑(varFinsetLeft t) ⊆ s
v : α → M
xs : γ → M
⊢ realize (Sum.elim (v ∘ Subtype.val) xs) (restrictVarLeft t (Set.inclusion h)) = realize (Sum.elim v xs) t

Next tactic:
induction' t with a _ _ _ ih
@[simp]
theorem realize_restrictVarLeft [DecidableEq α] {γ : Type*} {t : L.Term (Sum α γ)} {s : Set α}
    (h : ↑t.varFinsetLeft ⊆ s) {v : α → M} {xs : γ → M} :
    (t.restrictVarLeft (Set.inclusion h)).realize (Sum.elim (v ∘ (↑)) xs) =
      t.realize (Sum.elim v xs) := by
  induction' t with a _ _ _ ih
  · 

Proof state:
case var
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝³ : Structure L M
inst✝² : Structure L N
inst✝¹ : Structure L P
α : Type u'
β : Type v'
γ✝ : Type u_3
inst✝ : DecidableEq α
γ : Type u_4
s : Set α
v : α → M
xs : γ → M
a : α ⊕ γ
h : ↑(varFinsetLeft (var a)) ⊆ s
⊢ realize (Sum.elim (v ∘ Subtype.val) xs) (restrictVarLeft (var a) (Set.inclusion h)) = realize (Sum.elim v xs) (var a)

Next tactic:
cases a
@[simp]
theorem realize_restrictVarLeft [DecidableEq α] {γ : Type*} {t : L.Term (Sum α γ)} {s : Set α}
    (h : ↑t.varFinsetLeft ⊆ s) {v : α → M} {xs : γ → M} :
    (t.restrictVarLeft (Set.inclusion h)).realize (Sum.elim (v ∘ (↑)) xs) =
      t.realize (Sum.elim v xs) := by
  induction' t with a _ _ _ ih
  · cases a <;> 

Proof state:
case var.inl
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝³ : Structure L M
inst✝² : Structure L N
inst✝¹ : Structure L P
α : Type u'
β : Type v'
γ✝ : Type u_3
inst✝ : DecidableEq α
γ : Type u_4
s : Set α
v : α → M
xs : γ → M
val✝ : α
h : ↑(varFinsetLeft (var (Sum.inl val✝))) ⊆ s
⊢ realize (Sum.elim (v ∘ Subtype.val) xs) (restrictVarLeft (var (Sum.inl val✝)) (Set.inclusion h)) =
    realize (Sum.elim v xs) (var (Sum.inl val✝))

Next tactic:
rfl
@[simp]
theorem realize_restrictVarLeft [DecidableEq α] {γ : Type*} {t : L.Term (Sum α γ)} {s : Set α}
    (h : ↑t.varFinsetLeft ⊆ s) {v : α → M} {xs : γ → M} :
    (t.restrictVarLeft (Set.inclusion h)).realize (Sum.elim (v ∘ (↑)) xs) =
      t.realize (Sum.elim v xs) := by
  induction' t with a _ _ _ ih
  · cases a <;> 

Proof state:
case var.inr
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝³ : Structure L M
inst✝² : Structure L N
inst✝¹ : Structure L P
α : Type u'
β : Type v'
γ✝ : Type u_3
inst✝ : DecidableEq α
γ : Type u_4
s : Set α
v : α → M
xs : γ → M
val✝ : γ
h : ↑(varFinsetLeft (var (Sum.inr val✝))) ⊆ s
⊢ realize (Sum.elim (v ∘ Subtype.val) xs) (restrictVarLeft (var (Sum.inr val✝)) (Set.inclusion h)) =
    realize (Sum.elim v xs) (var (Sum.inr val✝))

Next tactic:
rfl
@[simp]
theorem realize_restrictVarLeft [DecidableEq α] {γ : Type*} {t : L.Term (Sum α γ)} {s : Set α}
    (h : ↑t.varFinsetLeft ⊆ s) {v : α → M} {xs : γ → M} :
    (t.restrictVarLeft (Set.inclusion h)).realize (Sum.elim (v ∘ (↑)) xs) =
      t.realize (Sum.elim v xs) := by
  induction' t with a _ _ _ ih
  · cases a <;> rfl
  · 

Proof state:
case func
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝³ : Structure L M
inst✝² : Structure L N
inst✝¹ : Structure L P
α : Type u'
β : Type v'
γ✝ : Type u_3
inst✝ : DecidableEq α
γ : Type u_4
s : Set α
v : α → M
xs : γ → M
l✝ : ℕ
_f✝ : Functions L l✝
_ts✝ : Fin l✝ → Term L (α ⊕ γ)
ih :
  ∀ (a : Fin l✝) (h : ↑(varFinsetLeft (_ts✝ a)) ⊆ s),
    realize (Sum.elim (v ∘ Subtype.val) xs) (restrictVarLeft (_ts✝ a) (Set.inclusion h)) =
      realize (Sum.elim v xs) (_ts✝ a)
h : ↑(varFinsetLeft (func _f✝ _ts✝)) ⊆ s
⊢ realize (Sum.elim (v ∘ Subtype.val) xs) (restrictVarLeft (func _f✝ _ts✝) (Set.inclusion h)) =
    realize (Sum.elim v xs) (func _f✝ _ts✝)

Next tactic:
simp_rw [varFinsetLeft, Finset.coe_biUnion, Set.iUnion_subset_iff] at h
@[simp]
theorem realize_restrictVarLeft [DecidableEq α] {γ : Type*} {t : L.Term (Sum α γ)} {s : Set α}
    (h : ↑t.varFinsetLeft ⊆ s) {v : α → M} {xs : γ → M} :
    (t.restrictVarLeft (Set.inclusion h)).realize (Sum.elim (v ∘ (↑)) xs) =
      t.realize (Sum.elim v xs) := by
  induction' t with a _ _ _ ih
  · cases a <;> rfl
  · simp_rw [varFinsetLeft, Finset.coe_biUnion, Set.iUnion_subset_iff] at h
    

Proof state:
case func
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝³ : Structure L M
inst✝² : Structure L N
inst✝¹ : Structure L P
α : Type u'
β : Type v'
γ✝ : Type u_3
inst✝ : DecidableEq α
γ : Type u_4
s : Set α
v : α → M
xs : γ → M
l✝ : ℕ
_f✝ : Functions L l✝
_ts✝ : Fin l✝ → Term L (α ⊕ γ)
ih :
  ∀ (a : Fin l✝) (h : ↑(varFinsetLeft (_ts✝ a)) ⊆ s),
    realize (Sum.elim (v ∘ Subtype.val) xs) (restrictVarLeft (_ts✝ a) (Set.inclusion h)) =
      realize (Sum.elim v xs) (_ts✝ a)
h✝ : ↑(Finset.biUnion Finset.univ fun i => varFinsetLeft (_ts✝ i)) ⊆ s
h : ∀ i ∈ ↑Finset.univ, ↑(varFinsetLeft (_ts✝ i)) ⊆ s
⊢ realize (Sum.elim (v ∘ Subtype.val) xs) (restrictVarLeft (func _f✝ _ts✝) (Set.inclusion h✝)) =
    realize (Sum.elim v xs) (func _f✝ _ts✝)

Next tactic:
exact congr rfl (funext fun i => ih i (h i (Finset.mem_univ i)))
@[simp]
theorem realize_constantsToVars [L[[α]].Structure M] [(lhomWithConstants L α).IsExpansionOn M]
    {t : L[[α]].Term β} {v : β → M} :
    t.constantsToVars.realize (Sum.elim (fun a => ↑(L.con a)) v) = t.realize v := by
  

Proof state:
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝⁴ : Structure L M
inst✝³ : Structure L N
inst✝² : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
inst✝¹ : Structure (L[[α]]) M
inst✝ : LHom.IsExpansionOn (lhomWithConstants L α) M
t : Term (L[[α]]) β
v : β → M
⊢ realize (Sum.elim (fun a => ↑(Language.con L a)) v) (constantsToVars t) = realize v t

Next tactic:
induction' t with _ n f ts ih
@[simp]
theorem realize_constantsToVars [L[[α]].Structure M] [(lhomWithConstants L α).IsExpansionOn M]
    {t : L[[α]].Term β} {v : β → M} :
    t.constantsToVars.realize (Sum.elim (fun a => ↑(L.con a)) v) = t.realize v := by
  induction' t with _ n f ts ih
  · 

Proof state:
case var
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝⁴ : Structure L M
inst✝³ : Structure L N
inst✝² : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
inst✝¹ : Structure (L[[α]]) M
inst✝ : LHom.IsExpansionOn (lhomWithConstants L α) M
v : β → M
_a✝ : β
⊢ realize (Sum.elim (fun a => ↑(Language.con L a)) v) (constantsToVars (var _a✝)) = realize v (var _a✝)

Next tactic:
simp
@[simp]
theorem realize_constantsToVars [L[[α]].Structure M] [(lhomWithConstants L α).IsExpansionOn M]
    {t : L[[α]].Term β} {v : β → M} :
    t.constantsToVars.realize (Sum.elim (fun a => ↑(L.con a)) v) = t.realize v := by
  induction' t with _ n f ts ih
  · simp
  · 

Proof state:
case func
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝⁴ : Structure L M
inst✝³ : Structure L N
inst✝² : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
inst✝¹ : Structure (L[[α]]) M
inst✝ : LHom.IsExpansionOn (lhomWithConstants L α) M
v : β → M
n : ℕ
f : Functions (L[[α]]) n
ts : Fin n → Term (L[[α]]) β
ih : ∀ (a : Fin n), realize (Sum.elim (fun a => ↑(Language.con L a)) v) (constantsToVars (ts a)) = realize v (ts a)
⊢ realize (Sum.elim (fun a => ↑(Language.con L a)) v) (constantsToVars (func f ts)) = realize v (func f ts)

Next tactic:
cases n
@[simp]
theorem realize_constantsToVars [L[[α]].Structure M] [(lhomWithConstants L α).IsExpansionOn M]
    {t : L[[α]].Term β} {v : β → M} :
    t.constantsToVars.realize (Sum.elim (fun a => ↑(L.con a)) v) = t.realize v := by
  induction' t with _ n f ts ih
  · simp
  · cases n
    · 

Proof state:
case func.zero
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝⁴ : Structure L M
inst✝³ : Structure L N
inst✝² : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
inst✝¹ : Structure (L[[α]]) M
inst✝ : LHom.IsExpansionOn (lhomWithConstants L α) M
v : β → M
f : Functions (L[[α]]) Nat.zero
ts : Fin Nat.zero → Term (L[[α]]) β
ih :
  ∀ (a : Fin Nat.zero), realize (Sum.elim (fun a => ↑(Language.con L a)) v) (constantsToVars (ts a)) = realize v (ts a)
⊢ realize (Sum.elim (fun a => ↑(Language.con L a)) v) (constantsToVars (func f ts)) = realize v (func f ts)

Next tactic:
cases f
@[simp]
theorem realize_constantsToVars [L[[α]].Structure M] [(lhomWithConstants L α).IsExpansionOn M]
    {t : L[[α]].Term β} {v : β → M} :
    t.constantsToVars.realize (Sum.elim (fun a => ↑(L.con a)) v) = t.realize v := by
  induction' t with _ n f ts ih
  · simp
  · cases n
    · cases f
      · 

Proof state:
case func.zero.inl
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝⁴ : Structure L M
inst✝³ : Structure L N
inst✝² : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
inst✝¹ : Structure (L[[α]]) M
inst✝ : LHom.IsExpansionOn (lhomWithConstants L α) M
v : β → M
ts : Fin Nat.zero → Term (L[[α]]) β
ih :
  ∀ (a : Fin Nat.zero), realize (Sum.elim (fun a => ↑(Language.con L a)) v) (constantsToVars (ts a)) = realize v (ts a)
val✝ : Functions L Nat.zero
⊢ realize (Sum.elim (fun a => ↑(Language.con L a)) v) (constantsToVars (func (Sum.inl val✝) ts)) =
    realize v (func (Sum.inl val✝) ts)

Next tactic:
simp only [realize, ih, Nat.zero_eq, constantsOn, mk₂_Functions]
@[simp]
theorem realize_constantsToVars [L[[α]].Structure M] [(lhomWithConstants L α).IsExpansionOn M]
    {t : L[[α]].Term β} {v : β → M} :
    t.constantsToVars.realize (Sum.elim (fun a => ↑(L.con a)) v) = t.realize v := by
  induction' t with _ n f ts ih
  · simp
  · cases n
    · cases f
      · simp only [realize, ih, Nat.zero_eq, constantsOn, mk₂_Functions]
        --Porting note: below lemma does not work with simp for some reason
        

Proof state:
case func.zero.inl
L : Language
L' : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝⁴ : Structure L M
inst✝³ : Structure L N
inst✝² : Structure L P
α : Type u'
β : Type v'
γ : Type u_3
inst✝¹ : Structure (L[[α]]) M
inst✝ : LHom.IsExpansionOn (lhomWithConstants L α) M
v : β → M
ts : Fin Nat.zero → Term (L[[α]]) β
ih :
  ∀ (a : Fin Nat.zero), realize (Sum.elim (fun a => ↑(Language.con L a)) v) (constantsToVars (ts a)) = realize v (ts a)
val✝ : Functions L Nat.zero
⊢ (funMap val✝ fun i => realize v (ts i)) = funMap (Sum.inl val✝) fun i => realize v (ts i)

Next tactic:
rw [withConstants_funMap_sum_inl]