l3lab/ntp-mathlib huggingface dataset:
instance instSemiring : Semiring (Language α) where
  add := (· + ·)
  add_assoc := union_assoc
  zero := 0
  zero_add := empty_union
  add_zero := union_empty
  add_comm := union_comm
  mul := (· * ·)
  mul_assoc _ _ _ := image2_assoc append_assoc
  zero_mul _ := image2_empty_left
  mul_zero _ := image2_empty_right
  one := 1
  one_mul l := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x : List α
l : Language α
⊢ 1 * l = l

Next tactic:
simp [mul_def, one_def]
instance instSemiring : Semiring (Language α) where
  add := (· + ·)
  add_assoc := union_assoc
  zero := 0
  zero_add := empty_union
  add_zero := union_empty
  add_comm := union_comm
  mul := (· * ·)
  mul_assoc _ _ _ := image2_assoc append_assoc
  zero_mul _ := image2_empty_left
  mul_zero _ := image2_empty_right
  one := 1
  one_mul l := by simp [mul_def, one_def]
  mul_one l := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x : List α
l : Language α
⊢ l * 1 = l

Next tactic:
simp [mul_def, one_def]
instance instSemiring : Semiring (Language α) where
  add := (· + ·)
  add_assoc := union_assoc
  zero := 0
  zero_add := empty_union
  add_zero := union_empty
  add_comm := union_comm
  mul := (· * ·)
  mul_assoc _ _ _ := image2_assoc append_assoc
  zero_mul _ := image2_empty_left
  mul_zero _ := image2_empty_right
  one := 1
  one_mul l := by simp [mul_def, one_def]
  mul_one l := by simp [mul_def, one_def]
  natCast n := if n = 0 then 0 else 1
  natCast_zero := rfl
  natCast_succ n := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
l m : Language α
a b x : List α
n : ℕ
⊢ NatCast.natCast (n + 1) = NatCast.natCast n + 1

Next tactic:
cases n
instance instSemiring : Semiring (Language α) where
  add := (· + ·)
  add_assoc := union_assoc
  zero := 0
  zero_add := empty_union
  add_zero := union_empty
  add_comm := union_comm
  mul := (· * ·)
  mul_assoc _ _ _ := image2_assoc append_assoc
  zero_mul _ := image2_empty_left
  mul_zero _ := image2_empty_right
  one := 1
  one_mul l := by simp [mul_def, one_def]
  mul_one l := by simp [mul_def, one_def]
  natCast n := if n = 0 then 0 else 1
  natCast_zero := rfl
  natCast_succ n := by cases n <;> 

Proof state:
case zero
α : Type u_1
β : Type u_2
γ : Type u_3
l m : Language α
a b x : List α
⊢ NatCast.natCast (Nat.zero + 1) = NatCast.natCast Nat.zero + 1

Next tactic:
simp [Nat.cast, add_def, zero_def]
instance instSemiring : Semiring (Language α) where
  add := (· + ·)
  add_assoc := union_assoc
  zero := 0
  zero_add := empty_union
  add_zero := union_empty
  add_comm := union_comm
  mul := (· * ·)
  mul_assoc _ _ _ := image2_assoc append_assoc
  zero_mul _ := image2_empty_left
  mul_zero _ := image2_empty_right
  one := 1
  one_mul l := by simp [mul_def, one_def]
  mul_one l := by simp [mul_def, one_def]
  natCast n := if n = 0 then 0 else 1
  natCast_zero := rfl
  natCast_succ n := by cases n <;> 

Proof state:
case succ
α : Type u_1
β : Type u_2
γ : Type u_3
l m : Language α
a b x : List α
n✝ : ℕ
⊢ NatCast.natCast (Nat.succ n✝ + 1) = NatCast.natCast (Nat.succ n✝) + 1

Next tactic:
simp [Nat.cast, add_def, zero_def]
@[simp]
theorem map_id (l : Language α) : map id l = l := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x : List α
l : Language α
⊢ (map id) l = l

Next tactic:
simp [map]
@[simp]
theorem map_map (g : β → γ) (f : α → β) (l : Language α) : map g (map f l) = map (g ∘ f) l := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x : List α
g : β → γ
f : α → β
l : Language α
⊢ (map g) ((map f) l) = (map (g ∘ f)) l

Next tactic:
simp [map, image_image]
theorem kstar_def_nonempty (l : Language α) :
    l∗ = { x | ∃ S : List (List α), x = S.join ∧ ∀ y ∈ S, y ∈ l ∧ y ≠ [] } := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x : List α
l : Language α
⊢ l∗ = {x | ∃ S, x = join S ∧ ∀ y ∈ S, y ∈ l ∧ y ≠ []}

Next tactic:
ext x
theorem kstar_def_nonempty (l : Language α) :
    l∗ = { x | ∃ S : List (List α), x = S.join ∧ ∀ y ∈ S, y ∈ l ∧ y ≠ [] } := by
  ext x
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x✝ : List α
l : Language α
x : List α
⊢ x ∈ l∗ ↔ x ∈ {x | ∃ S, x = join S ∧ ∀ y ∈ S, y ∈ l ∧ y ≠ []}

Next tactic:
constructor
theorem kstar_def_nonempty (l : Language α) :
    l∗ = { x | ∃ S : List (List α), x = S.join ∧ ∀ y ∈ S, y ∈ l ∧ y ≠ [] } := by
  ext x
  constructor
  · 

Proof state:
case h.mp
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x✝ : List α
l : Language α
x : List α
⊢ x ∈ l∗ → x ∈ {x | ∃ S, x = join S ∧ ∀ y ∈ S, y ∈ l ∧ y ≠ []}

Next tactic:
rintro ⟨S, rfl, h⟩
theorem kstar_def_nonempty (l : Language α) :
    l∗ = { x | ∃ S : List (List α), x = S.join ∧ ∀ y ∈ S, y ∈ l ∧ y ≠ [] } := by
  ext x
  constructor
  · rintro ⟨S, rfl, h⟩
    

Proof state:
case h.mp.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x : List α
l : Language α
S : List (List α)
h : ∀ y ∈ S, y ∈ l
⊢ join S ∈ {x | ∃ S, x = join S ∧ ∀ y ∈ S, y ∈ l ∧ y ≠ []}

Next tactic:
refine' ⟨S.filter fun l ↦ ¬List.isEmpty l, by simp, fun y hy ↦ _⟩
theorem kstar_def_nonempty (l : Language α) :
    l∗ = { x | ∃ S : List (List α), x = S.join ∧ ∀ y ∈ S, y ∈ l ∧ y ≠ [] } := by
  ext x
  constructor
  · rintro ⟨S, rfl, h⟩
    refine' ⟨S.filter fun l ↦ ¬List.isEmpty l, by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x : List α
l : Language α
S : List (List α)
h : ∀ y ∈ S, y ∈ l
⊢ join S = join (filter (fun l => decide ¬isEmpty l = true) S)

Next tactic:
simp
theorem kstar_def_nonempty (l : Language α) :
    l∗ = { x | ∃ S : List (List α), x = S.join ∧ ∀ y ∈ S, y ∈ l ∧ y ≠ [] } := by
  ext x
  constructor
  · rintro ⟨S, rfl, h⟩
    refine' ⟨S.filter fun l ↦ ¬List.isEmpty l, by simp, fun y hy ↦ _⟩
    -- Porting note: The previous code was:
    -- rw [mem_filter, empty_iff_eq_nil] at hy
    

Proof state:
case h.mp.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x : List α
l : Language α
S : List (List α)
h : ∀ y ∈ S, y ∈ l
y : List α
hy : y ∈ filter (fun l => decide ¬isEmpty l = true) S
⊢ y ∈ l ∧ y ≠ []

Next tactic:
rw [mem_filter, decide_not, Bool.decide_coe, Bool.not_eq_true', ← Bool.bool_iff_false,
      isEmpty_iff_eq_nil] at hy
theorem kstar_def_nonempty (l : Language α) :
    l∗ = { x | ∃ S : List (List α), x = S.join ∧ ∀ y ∈ S, y ∈ l ∧ y ≠ [] } := by
  ext x
  constructor
  · rintro ⟨S, rfl, h⟩
    refine' ⟨S.filter fun l ↦ ¬List.isEmpty l, by simp, fun y hy ↦ _⟩
    -- Porting note: The previous code was:
    -- rw [mem_filter, empty_iff_eq_nil] at hy
    rw [mem_filter, decide_not, Bool.decide_coe, Bool.not_eq_true', ← Bool.bool_iff_false,
      isEmpty_iff_eq_nil] at hy
    

Proof state:
case h.mp.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x : List α
l : Language α
S : List (List α)
h : ∀ y ∈ S, y ∈ l
y : List α
hy : y ∈ S ∧ ¬y = []
⊢ y ∈ l ∧ y ≠ []

Next tactic:
exact ⟨h y hy.1, hy.2⟩
theorem kstar_def_nonempty (l : Language α) :
    l∗ = { x | ∃ S : List (List α), x = S.join ∧ ∀ y ∈ S, y ∈ l ∧ y ≠ [] } := by
  ext x
  constructor
  · rintro ⟨S, rfl, h⟩
    refine' ⟨S.filter fun l ↦ ¬List.isEmpty l, by simp, fun y hy ↦ _⟩
    -- Porting note: The previous code was:
    -- rw [mem_filter, empty_iff_eq_nil] at hy
    rw [mem_filter, decide_not, Bool.decide_coe, Bool.not_eq_true', ← Bool.bool_iff_false,
      isEmpty_iff_eq_nil] at hy
    exact ⟨h y hy.1, hy.2⟩
  · 

Proof state:
case h.mpr
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x✝ : List α
l : Language α
x : List α
⊢ x ∈ {x | ∃ S, x = join S ∧ ∀ y ∈ S, y ∈ l ∧ y ≠ []} → x ∈ l∗

Next tactic:
rintro ⟨S, hx, h⟩
theorem kstar_def_nonempty (l : Language α) :
    l∗ = { x | ∃ S : List (List α), x = S.join ∧ ∀ y ∈ S, y ∈ l ∧ y ≠ [] } := by
  ext x
  constructor
  · rintro ⟨S, rfl, h⟩
    refine' ⟨S.filter fun l ↦ ¬List.isEmpty l, by simp, fun y hy ↦ _⟩
    -- Porting note: The previous code was:
    -- rw [mem_filter, empty_iff_eq_nil] at hy
    rw [mem_filter, decide_not, Bool.decide_coe, Bool.not_eq_true', ← Bool.bool_iff_false,
      isEmpty_iff_eq_nil] at hy
    exact ⟨h y hy.1, hy.2⟩
  · rintro ⟨S, hx, h⟩
    

Proof state:
case h.mpr.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x✝ : List α
l : Language α
x : List α
S : List (List α)
hx : x = join S
h : ∀ y ∈ S, y ∈ l ∧ y ≠ []
⊢ x ∈ l∗

Next tactic:
exact ⟨S, hx, fun y hy ↦ (h y hy).1⟩
theorem le_mul_congr {l₁ l₂ m₁ m₂ : Language α} : l₁ ≤ m₁ → l₂ ≤ m₂ → l₁ * l₂ ≤ m₁ * m₂ := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
l m : Language α
a b x : List α
l₁ l₂ m₁ m₂ : Language α
⊢ l₁ ≤ m₁ → l₂ ≤ m₂ → l₁ * l₂ ≤ m₁ * m₂

Next tactic:
intro h₁ h₂ x hx
theorem le_mul_congr {l₁ l₂ m₁ m₂ : Language α} : l₁ ≤ m₁ → l₂ ≤ m₂ → l₁ * l₂ ≤ m₁ * m₂ := by
  intro h₁ h₂ x hx
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
l m : Language α
a b x✝ : List α
l₁ l₂ m₁ m₂ : Language α
h₁ : l₁ ≤ m₁
h₂ : l₂ ≤ m₂
x : List α
hx : x ∈ l₁ * l₂
⊢ x ∈ m₁ * m₂

Next tactic:
simp only [mul_def, exists_and_left, mem_image2, image_prod] at hx ⊢
theorem le_mul_congr {l₁ l₂ m₁ m₂ : Language α} : l₁ ≤ m₁ → l₂ ≤ m₂ → l₁ * l₂ ≤ m₁ * m₂ := by
  intro h₁ h₂ x hx
  simp only [mul_def, exists_and_left, mem_image2, image_prod] at hx ⊢
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
l m : Language α
a b x✝ : List α
l₁ l₂ m₁ m₂ : Language α
h₁ : l₁ ≤ m₁
h₂ : l₂ ≤ m₂
x : List α
hx : ∃ a ∈ l₁, ∃ x_1 ∈ l₂, a ++ x_1 = x
⊢ ∃ a ∈ m₁, ∃ x_1 ∈ m₂, a ++ x_1 = x

Next tactic:
tauto
theorem mem_pow {l : Language α} {x : List α} {n : ℕ} :
    x ∈ l ^ n ↔ ∃ S : List (List α), x = S.join ∧ S.length = n ∧ ∀ y ∈ S, y ∈ l := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x✝ : List α
l : Language α
x : List α
n : ℕ
⊢ x ∈ l ^ n ↔ ∃ S, x = join S ∧ length S = n ∧ ∀ y ∈ S, y ∈ l

Next tactic:
induction' n with n ihn generalizing x
theorem mem_pow {l : Language α} {x : List α} {n : ℕ} :
    x ∈ l ^ n ↔ ∃ S : List (List α), x = S.join ∧ S.length = n ∧ ∀ y ∈ S, y ∈ l := by
  induction' n with n ihn generalizing x
  · 

Proof state:
case zero
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x✝ : List α
l : Language α
x : List α
⊢ x ∈ l ^ Nat.zero ↔ ∃ S, x = join S ∧ length S = Nat.zero ∧ ∀ y ∈ S, y ∈ l

Next tactic:
simp only [mem_one, pow_zero, length_eq_zero]
theorem mem_pow {l : Language α} {x : List α} {n : ℕ} :
    x ∈ l ^ n ↔ ∃ S : List (List α), x = S.join ∧ S.length = n ∧ ∀ y ∈ S, y ∈ l := by
  induction' n with n ihn generalizing x
  · simp only [mem_one, pow_zero, length_eq_zero]
    

Proof state:
case zero
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x✝ : List α
l : Language α
x : List α
⊢ x = [] ↔ ∃ S, x = join S ∧ S = [] ∧ ∀ y ∈ S, y ∈ l

Next tactic:
constructor
theorem mem_pow {l : Language α} {x : List α} {n : ℕ} :
    x ∈ l ^ n ↔ ∃ S : List (List α), x = S.join ∧ S.length = n ∧ ∀ y ∈ S, y ∈ l := by
  induction' n with n ihn generalizing x
  · simp only [mem_one, pow_zero, length_eq_zero]
    constructor
    · 

Proof state:
case zero.mp
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x✝ : List α
l : Language α
x : List α
⊢ x = [] → ∃ S, x = join S ∧ S = [] ∧ ∀ y ∈ S, y ∈ l

Next tactic:
rintro rfl
theorem mem_pow {l : Language α} {x : List α} {n : ℕ} :
    x ∈ l ^ n ↔ ∃ S : List (List α), x = S.join ∧ S.length = n ∧ ∀ y ∈ S, y ∈ l := by
  induction' n with n ihn generalizing x
  · simp only [mem_one, pow_zero, length_eq_zero]
    constructor
    · rintro rfl
      

Proof state:
case zero.mp
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x : List α
l : Language α
⊢ ∃ S, [] = join S ∧ S = [] ∧ ∀ y ∈ S, y ∈ l

Next tactic:
exact ⟨[], rfl, rfl, fun _ h ↦ by contradiction⟩
theorem mem_pow {l : Language α} {x : List α} {n : ℕ} :
    x ∈ l ^ n ↔ ∃ S : List (List α), x = S.join ∧ S.length = n ∧ ∀ y ∈ S, y ∈ l := by
  induction' n with n ihn generalizing x
  · simp only [mem_one, pow_zero, length_eq_zero]
    constructor
    · rintro rfl
      exact ⟨[], rfl, rfl, fun _ h ↦ by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x : List α
l : Language α
x✝ : List α
h : x✝ ∈ []
⊢ x✝ ∈ l

Next tactic:
contradiction
theorem mem_pow {l : Language α} {x : List α} {n : ℕ} :
    x ∈ l ^ n ↔ ∃ S : List (List α), x = S.join ∧ S.length = n ∧ ∀ y ∈ S, y ∈ l := by
  induction' n with n ihn generalizing x
  · simp only [mem_one, pow_zero, length_eq_zero]
    constructor
    · rintro rfl
      exact ⟨[], rfl, rfl, fun _ h ↦ by contradiction⟩
    · 

Proof state:
case zero.mpr
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x✝ : List α
l : Language α
x : List α
⊢ (∃ S, x = join S ∧ S = [] ∧ ∀ y ∈ S, y ∈ l) → x = []

Next tactic:
rintro ⟨_, rfl, rfl, _⟩
theorem mem_pow {l : Language α} {x : List α} {n : ℕ} :
    x ∈ l ^ n ↔ ∃ S : List (List α), x = S.join ∧ S.length = n ∧ ∀ y ∈ S, y ∈ l := by
  induction' n with n ihn generalizing x
  · simp only [mem_one, pow_zero, length_eq_zero]
    constructor
    · rintro rfl
      exact ⟨[], rfl, rfl, fun _ h ↦ by contradiction⟩
    · rintro ⟨_, rfl, rfl, _⟩
      

Proof state:
case zero.mpr.intro.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x : List α
l : Language α
right✝ : ∀ y ∈ [], y ∈ l
⊢ join [] = []

Next tactic:
rfl
theorem mem_pow {l : Language α} {x : List α} {n : ℕ} :
    x ∈ l ^ n ↔ ∃ S : List (List α), x = S.join ∧ S.length = n ∧ ∀ y ∈ S, y ∈ l := by
  induction' n with n ihn generalizing x
  · simp only [mem_one, pow_zero, length_eq_zero]
    constructor
    · rintro rfl
      exact ⟨[], rfl, rfl, fun _ h ↦ by contradiction⟩
    · rintro ⟨_, rfl, rfl, _⟩
      rfl
  · 

Proof state:
case succ
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x✝ : List α
l : Language α
n : ℕ
ihn : ∀ {x : List α}, x ∈ l ^ n ↔ ∃ S, x = join S ∧ length S = n ∧ ∀ y ∈ S, y ∈ l
x : List α
⊢ x ∈ l ^ Nat.succ n ↔ ∃ S, x = join S ∧ length S = Nat.succ n ∧ ∀ y ∈ S, y ∈ l

Next tactic:
simp only [pow_succ, mem_mul, ihn]
theorem mem_pow {l : Language α} {x : List α} {n : ℕ} :
    x ∈ l ^ n ↔ ∃ S : List (List α), x = S.join ∧ S.length = n ∧ ∀ y ∈ S, y ∈ l := by
  induction' n with n ihn generalizing x
  · simp only [mem_one, pow_zero, length_eq_zero]
    constructor
    · rintro rfl
      exact ⟨[], rfl, rfl, fun _ h ↦ by contradiction⟩
    · rintro ⟨_, rfl, rfl, _⟩
      rfl
  · simp only [pow_succ, mem_mul, ihn]
    

Proof state:
case succ
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x✝ : List α
l : Language α
n : ℕ
ihn : ∀ {x : List α}, x ∈ l ^ n ↔ ∃ S, x = join S ∧ length S = n ∧ ∀ y ∈ S, y ∈ l
x : List α
⊢ (∃ a b, a ∈ l ∧ (∃ S, b = join S ∧ length S = n ∧ ∀ y ∈ S, y ∈ l) ∧ a ++ b = x) ↔
    ∃ S, x = join S ∧ length S = Nat.succ n ∧ ∀ y ∈ S, y ∈ l

Next tactic:
constructor
theorem mem_pow {l : Language α} {x : List α} {n : ℕ} :
    x ∈ l ^ n ↔ ∃ S : List (List α), x = S.join ∧ S.length = n ∧ ∀ y ∈ S, y ∈ l := by
  induction' n with n ihn generalizing x
  · simp only [mem_one, pow_zero, length_eq_zero]
    constructor
    · rintro rfl
      exact ⟨[], rfl, rfl, fun _ h ↦ by contradiction⟩
    · rintro ⟨_, rfl, rfl, _⟩
      rfl
  · simp only [pow_succ, mem_mul, ihn]
    constructor
    · 

Proof state:
case succ.mp
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x✝ : List α
l : Language α
n : ℕ
ihn : ∀ {x : List α}, x ∈ l ^ n ↔ ∃ S, x = join S ∧ length S = n ∧ ∀ y ∈ S, y ∈ l
x : List α
⊢ (∃ a b, a ∈ l ∧ (∃ S, b = join S ∧ length S = n ∧ ∀ y ∈ S, y ∈ l) ∧ a ++ b = x) →
    ∃ S, x = join S ∧ length S = Nat.succ n ∧ ∀ y ∈ S, y ∈ l

Next tactic:
rintro ⟨a, b, ha, ⟨S, rfl, rfl, hS⟩, rfl⟩
theorem mem_pow {l : Language α} {x : List α} {n : ℕ} :
    x ∈ l ^ n ↔ ∃ S : List (List α), x = S.join ∧ S.length = n ∧ ∀ y ∈ S, y ∈ l := by
  induction' n with n ihn generalizing x
  · simp only [mem_one, pow_zero, length_eq_zero]
    constructor
    · rintro rfl
      exact ⟨[], rfl, rfl, fun _ h ↦ by contradiction⟩
    · rintro ⟨_, rfl, rfl, _⟩
      rfl
  · simp only [pow_succ, mem_mul, ihn]
    constructor
    · rintro ⟨a, b, ha, ⟨S, rfl, rfl, hS⟩, rfl⟩
      

Proof state:
case succ.mp.intro.intro.intro.intro.intro.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a✝ b x : List α
l : Language α
a : List α
ha : a ∈ l
S : List (List α)
hS : ∀ y ∈ S, y ∈ l
ihn : ∀ {x : List α}, x ∈ l ^ length S ↔ ∃ S_1, x = join S_1 ∧ length S_1 = length S ∧ ∀ y ∈ S_1, y ∈ l
⊢ ∃ S_1, a ++ join S = join S_1 ∧ length S_1 = Nat.succ (length S) ∧ ∀ y ∈ S_1, y ∈ l

Next tactic:
exact ⟨a :: S, rfl, rfl, forall_mem_cons.2 ⟨ha, hS⟩⟩
theorem mem_pow {l : Language α} {x : List α} {n : ℕ} :
    x ∈ l ^ n ↔ ∃ S : List (List α), x = S.join ∧ S.length = n ∧ ∀ y ∈ S, y ∈ l := by
  induction' n with n ihn generalizing x
  · simp only [mem_one, pow_zero, length_eq_zero]
    constructor
    · rintro rfl
      exact ⟨[], rfl, rfl, fun _ h ↦ by contradiction⟩
    · rintro ⟨_, rfl, rfl, _⟩
      rfl
  · simp only [pow_succ, mem_mul, ihn]
    constructor
    · rintro ⟨a, b, ha, ⟨S, rfl, rfl, hS⟩, rfl⟩
      exact ⟨a :: S, rfl, rfl, forall_mem_cons.2 ⟨ha, hS⟩⟩
    · 

Proof state:
case succ.mpr
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x✝ : List α
l : Language α
n : ℕ
ihn : ∀ {x : List α}, x ∈ l ^ n ↔ ∃ S, x = join S ∧ length S = n ∧ ∀ y ∈ S, y ∈ l
x : List α
⊢ (∃ S, x = join S ∧ length S = Nat.succ n ∧ ∀ y ∈ S, y ∈ l) →
    ∃ a b, a ∈ l ∧ (∃ S, b = join S ∧ length S = n ∧ ∀ y ∈ S, y ∈ l) ∧ a ++ b = x

Next tactic:
rintro ⟨_ | ⟨a, S⟩, rfl, hn, hS⟩
theorem mem_pow {l : Language α} {x : List α} {n : ℕ} :
    x ∈ l ^ n ↔ ∃ S : List (List α), x = S.join ∧ S.length = n ∧ ∀ y ∈ S, y ∈ l := by
  induction' n with n ihn generalizing x
  · simp only [mem_one, pow_zero, length_eq_zero]
    constructor
    · rintro rfl
      exact ⟨[], rfl, rfl, fun _ h ↦ by contradiction⟩
    · rintro ⟨_, rfl, rfl, _⟩
      rfl
  · simp only [pow_succ, mem_mul, ihn]
    constructor
    · rintro ⟨a, b, ha, ⟨S, rfl, rfl, hS⟩, rfl⟩
      exact ⟨a :: S, rfl, rfl, forall_mem_cons.2 ⟨ha, hS⟩⟩
    · rintro ⟨_ | ⟨a, S⟩, rfl, hn, hS⟩ <;> 

Proof state:
case succ.mpr.intro.nil.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x : List α
l : Language α
n : ℕ
ihn : ∀ {x : List α}, x ∈ l ^ n ↔ ∃ S, x = join S ∧ length S = n ∧ ∀ y ∈ S, y ∈ l
hn : length [] = Nat.succ n
hS : ∀ y ∈ [], y ∈ l
⊢ ∃ a b, a ∈ l ∧ (∃ S, b = join S ∧ length S = n ∧ ∀ y ∈ S, y ∈ l) ∧ a ++ b = join []

Next tactic:
cases hn
theorem mem_pow {l : Language α} {x : List α} {n : ℕ} :
    x ∈ l ^ n ↔ ∃ S : List (List α), x = S.join ∧ S.length = n ∧ ∀ y ∈ S, y ∈ l := by
  induction' n with n ihn generalizing x
  · simp only [mem_one, pow_zero, length_eq_zero]
    constructor
    · rintro rfl
      exact ⟨[], rfl, rfl, fun _ h ↦ by contradiction⟩
    · rintro ⟨_, rfl, rfl, _⟩
      rfl
  · simp only [pow_succ, mem_mul, ihn]
    constructor
    · rintro ⟨a, b, ha, ⟨S, rfl, rfl, hS⟩, rfl⟩
      exact ⟨a :: S, rfl, rfl, forall_mem_cons.2 ⟨ha, hS⟩⟩
    · rintro ⟨_ | ⟨a, S⟩, rfl, hn, hS⟩ <;> 

Proof state:
case succ.mpr.intro.cons.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a✝ b x : List α
l : Language α
n : ℕ
ihn : ∀ {x : List α}, x ∈ l ^ n ↔ ∃ S, x = join S ∧ length S = n ∧ ∀ y ∈ S, y ∈ l
a : List α
S : List (List α)
hn : length (a :: S) = Nat.succ n
hS : ∀ y ∈ a :: S, y ∈ l
⊢ ∃ a_1 b, a_1 ∈ l ∧ (∃ S, b = join S ∧ length S = n ∧ ∀ y ∈ S, y ∈ l) ∧ a_1 ++ b = join (a :: S)

Next tactic:
cases hn
theorem mem_pow {l : Language α} {x : List α} {n : ℕ} :
    x ∈ l ^ n ↔ ∃ S : List (List α), x = S.join ∧ S.length = n ∧ ∀ y ∈ S, y ∈ l := by
  induction' n with n ihn generalizing x
  · simp only [mem_one, pow_zero, length_eq_zero]
    constructor
    · rintro rfl
      exact ⟨[], rfl, rfl, fun _ h ↦ by contradiction⟩
    · rintro ⟨_, rfl, rfl, _⟩
      rfl
  · simp only [pow_succ, mem_mul, ihn]
    constructor
    · rintro ⟨a, b, ha, ⟨S, rfl, rfl, hS⟩, rfl⟩
      exact ⟨a :: S, rfl, rfl, forall_mem_cons.2 ⟨ha, hS⟩⟩
    · rintro ⟨_ | ⟨a, S⟩, rfl, hn, hS⟩ <;> cases hn
      

Proof state:
case succ.mpr.intro.cons.intro.intro.refl
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a✝ b x : List α
l : Language α
a : List α
S : List (List α)
hS : ∀ y ∈ a :: S, y ∈ l
ihn :
  ∀ {x : List α},
    x ∈ l ^ Nat.add (length S) 0 ↔ ∃ S_1, x = join S_1 ∧ length S_1 = Nat.add (length S) 0 ∧ ∀ y ∈ S_1, y ∈ l
⊢ ∃ a_1 b,
    a_1 ∈ l ∧ (∃ S_1, b = join S_1 ∧ length S_1 = Nat.add (length S) 0 ∧ ∀ y ∈ S_1, y ∈ l) ∧ a_1 ++ b = join (a :: S)

Next tactic:
rw [forall_mem_cons] at hS
theorem mem_pow {l : Language α} {x : List α} {n : ℕ} :
    x ∈ l ^ n ↔ ∃ S : List (List α), x = S.join ∧ S.length = n ∧ ∀ y ∈ S, y ∈ l := by
  induction' n with n ihn generalizing x
  · simp only [mem_one, pow_zero, length_eq_zero]
    constructor
    · rintro rfl
      exact ⟨[], rfl, rfl, fun _ h ↦ by contradiction⟩
    · rintro ⟨_, rfl, rfl, _⟩
      rfl
  · simp only [pow_succ, mem_mul, ihn]
    constructor
    · rintro ⟨a, b, ha, ⟨S, rfl, rfl, hS⟩, rfl⟩
      exact ⟨a :: S, rfl, rfl, forall_mem_cons.2 ⟨ha, hS⟩⟩
    · rintro ⟨_ | ⟨a, S⟩, rfl, hn, hS⟩ <;> cases hn
      rw [forall_mem_cons] at hS
      

Proof state:
case succ.mpr.intro.cons.intro.intro.refl
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a✝ b x : List α
l : Language α
a : List α
S : List (List α)
hS : a ∈ l ∧ ∀ x ∈ S, x ∈ l
ihn :
  ∀ {x : List α},
    x ∈ l ^ Nat.add (length S) 0 ↔ ∃ S_1, x = join S_1 ∧ length S_1 = Nat.add (length S) 0 ∧ ∀ y ∈ S_1, y ∈ l
⊢ ∃ a_1 b,
    a_1 ∈ l ∧ (∃ S_1, b = join S_1 ∧ length S_1 = Nat.add (length S) 0 ∧ ∀ y ∈ S_1, y ∈ l) ∧ a_1 ++ b = join (a :: S)

Next tactic:
exact ⟨a, _, hS.1, ⟨S, rfl, rfl, hS.2⟩, rfl⟩
theorem kstar_eq_iSup_pow (l : Language α) : l∗ = ⨆ i : ℕ, l ^ i := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x : List α
l : Language α
⊢ l∗ = ⨆ i, l ^ i

Next tactic:
ext x
theorem kstar_eq_iSup_pow (l : Language α) : l∗ = ⨆ i : ℕ, l ^ i := by
  ext x
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x✝ : List α
l : Language α
x : List α
⊢ x ∈ l∗ ↔ x ∈ ⨆ i, l ^ i

Next tactic:
simp only [mem_kstar, mem_iSup, mem_pow]
theorem kstar_eq_iSup_pow (l : Language α) : l∗ = ⨆ i : ℕ, l ^ i := by
  ext x
  simp only [mem_kstar, mem_iSup, mem_pow]
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x✝ : List α
l : Language α
x : List α
⊢ (∃ L, x = join L ∧ ∀ y ∈ L, y ∈ l) ↔ ∃ i S, x = join S ∧ length S = i ∧ ∀ y ∈ S, y ∈ l

Next tactic:
constructor
theorem kstar_eq_iSup_pow (l : Language α) : l∗ = ⨆ i : ℕ, l ^ i := by
  ext x
  simp only [mem_kstar, mem_iSup, mem_pow]
  constructor
  · 

Proof state:
case h.mp
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x✝ : List α
l : Language α
x : List α
⊢ (∃ L, x = join L ∧ ∀ y ∈ L, y ∈ l) → ∃ i S, x = join S ∧ length S = i ∧ ∀ y ∈ S, y ∈ l

Next tactic:
rintro ⟨S, rfl, hS⟩
theorem kstar_eq_iSup_pow (l : Language α) : l∗ = ⨆ i : ℕ, l ^ i := by
  ext x
  simp only [mem_kstar, mem_iSup, mem_pow]
  constructor
  · rintro ⟨S, rfl, hS⟩
    

Proof state:
case h.mp.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x : List α
l : Language α
S : List (List α)
hS : ∀ y ∈ S, y ∈ l
⊢ ∃ i S_1, join S = join S_1 ∧ length S_1 = i ∧ ∀ y ∈ S_1, y ∈ l

Next tactic:
exact ⟨_, S, rfl, rfl, hS⟩
theorem kstar_eq_iSup_pow (l : Language α) : l∗ = ⨆ i : ℕ, l ^ i := by
  ext x
  simp only [mem_kstar, mem_iSup, mem_pow]
  constructor
  · rintro ⟨S, rfl, hS⟩
    exact ⟨_, S, rfl, rfl, hS⟩
  · 

Proof state:
case h.mpr
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x✝ : List α
l : Language α
x : List α
⊢ (∃ i S, x = join S ∧ length S = i ∧ ∀ y ∈ S, y ∈ l) → ∃ L, x = join L ∧ ∀ y ∈ L, y ∈ l

Next tactic:
rintro ⟨_, S, rfl, rfl, hS⟩
theorem kstar_eq_iSup_pow (l : Language α) : l∗ = ⨆ i : ℕ, l ^ i := by
  ext x
  simp only [mem_kstar, mem_iSup, mem_pow]
  constructor
  · rintro ⟨S, rfl, hS⟩
    exact ⟨_, S, rfl, rfl, hS⟩
  · rintro ⟨_, S, rfl, rfl, hS⟩
    

Proof state:
case h.mpr.intro.intro.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
l✝ m : Language α
a b x : List α
l : Language α
S : List (List α)
hS : ∀ y ∈ S, y ∈ l
⊢ ∃ L, join S = join L ∧ ∀ y ∈ L, y ∈ l

Next tactic:
exact ⟨S, rfl, hS⟩