l3lab/ntp-mathlib huggingface dataset:
/-- An open immersion is isomorphic to the induced open subscheme on its image. -/
noncomputable def isoRestrict {X Y : LocallyRingedSpace} {f : X ⟶ Y}
    (H : LocallyRingedSpace.IsOpenImmersion f) :
    X ≅ Y.restrict H.base_open := by
  apply LocallyRingedSpace.isoOfSheafedSpaceIso
  refine' SheafedSpace.forgetToPresheafedSpace.preimageIso _
  

Proof state:
case f
C : Type u_1
inst✝ : Category.{?u.554179, u_1} C
X Y : LocallyRingedSpace
f : X ⟶ Y
H : IsOpenImmersion f
⊢ SheafedSpace.forgetToPresheafedSpace.obj X.toSheafedSpace ≅
    SheafedSpace.forgetToPresheafedSpace.obj (restrict Y (_ : OpenEmbedding ⇑f.val.base)).toSheafedSpace

Next tactic:
exact PresheafedSpace.IsOpenImmersion.isoRestrict H
@[simp]
theorem cardinal_mk_eq_max_lift [Nonempty σ] [Nontrivial R] :
    #(MvPolynomial σ R) = max (max (Cardinal.lift.{u} #R) <| Cardinal.lift.{v} #σ) ℵ₀ :=
  (mk_finsupp_lift_of_infinite _ R).trans <| by
    

Proof state:
σ : Type u
R : Type v
inst✝² : CommSemiring R
inst✝¹ : Nonempty σ
inst✝ : Nontrivial R
⊢ max (lift.{v, u} #(σ →₀ ℕ)) (lift.{u, v} #R) = max (max (lift.{u, v} #R) (lift.{v, u} #σ)) ℵ₀

Next tactic:
rw [mk_finsupp_nat, max_assoc, lift_max, lift_aleph0, max_comm]
theorem cardinal_lift_mk_le_max {σ : Type u} {R : Type v} [CommSemiring R] : #(MvPolynomial σ R) ≤
    max (max (Cardinal.lift.{u} #R) <| Cardinal.lift.{v} #σ) ℵ₀ := by
  

Proof state:
σ✝ : Type u
R✝ : Type v
inst✝¹ : CommSemiring R✝
σ : Type u
R : Type v
inst✝ : CommSemiring R
⊢ #(MvPolynomial σ R) ≤ max (max (lift.{u, v} #R) (lift.{v, u} #σ)) ℵ₀

Next tactic:
cases subsingleton_or_nontrivial R
theorem cardinal_lift_mk_le_max {σ : Type u} {R : Type v} [CommSemiring R] : #(MvPolynomial σ R) ≤
    max (max (Cardinal.lift.{u} #R) <| Cardinal.lift.{v} #σ) ℵ₀ := by
  cases subsingleton_or_nontrivial R
  · 

Proof state:
case inl
σ✝ : Type u
R✝ : Type v
inst✝¹ : CommSemiring R✝
σ : Type u
R : Type v
inst✝ : CommSemiring R
h✝ : Subsingleton R
⊢ #(MvPolynomial σ R) ≤ max (max (lift.{u, v} #R) (lift.{v, u} #σ)) ℵ₀

Next tactic:
exact (mk_eq_one _).trans_le (le_max_of_le_right one_le_aleph0)
theorem cardinal_lift_mk_le_max {σ : Type u} {R : Type v} [CommSemiring R] : #(MvPolynomial σ R) ≤
    max (max (Cardinal.lift.{u} #R) <| Cardinal.lift.{v} #σ) ℵ₀ := by
  cases subsingleton_or_nontrivial R
  · exact (mk_eq_one _).trans_le (le_max_of_le_right one_le_aleph0)
  

Proof state:
case inr
σ✝ : Type u
R✝ : Type v
inst✝¹ : CommSemiring R✝
σ : Type u
R : Type v
inst✝ : CommSemiring R
h✝ : Nontrivial R
⊢ #(MvPolynomial σ R) ≤ max (max (lift.{u, v} #R) (lift.{v, u} #σ)) ℵ₀

Next tactic:
cases isEmpty_or_nonempty σ
theorem cardinal_lift_mk_le_max {σ : Type u} {R : Type v} [CommSemiring R] : #(MvPolynomial σ R) ≤
    max (max (Cardinal.lift.{u} #R) <| Cardinal.lift.{v} #σ) ℵ₀ := by
  cases subsingleton_or_nontrivial R
  · exact (mk_eq_one _).trans_le (le_max_of_le_right one_le_aleph0)
  cases isEmpty_or_nonempty σ
  · 

Proof state:
case inr.inl
σ✝ : Type u
R✝ : Type v
inst✝¹ : CommSemiring R✝
σ : Type u
R : Type v
inst✝ : CommSemiring R
h✝¹ : Nontrivial R
h✝ : IsEmpty σ
⊢ #(MvPolynomial σ R) ≤ max (max (lift.{u, v} #R) (lift.{v, u} #σ)) ℵ₀

Next tactic:
exact cardinal_mk_eq_lift.trans_le (le_max_of_le_left <| le_max_left _ _)
theorem cardinal_lift_mk_le_max {σ : Type u} {R : Type v} [CommSemiring R] : #(MvPolynomial σ R) ≤
    max (max (Cardinal.lift.{u} #R) <| Cardinal.lift.{v} #σ) ℵ₀ := by
  cases subsingleton_or_nontrivial R
  · exact (mk_eq_one _).trans_le (le_max_of_le_right one_le_aleph0)
  cases isEmpty_or_nonempty σ
  · exact cardinal_mk_eq_lift.trans_le (le_max_of_le_left <| le_max_left _ _)
  · 

Proof state:
case inr.inr
σ✝ : Type u
R✝ : Type v
inst✝¹ : CommSemiring R✝
σ : Type u
R : Type v
inst✝ : CommSemiring R
h✝¹ : Nontrivial R
h✝ : Nonempty σ
⊢ #(MvPolynomial σ R) ≤ max (max (lift.{u, v} #R) (lift.{v, u} #σ)) ℵ₀

Next tactic:
exact cardinal_mk_eq_max_lift.le
theorem cardinal_mk_eq_max [Nonempty σ] [Nontrivial R] :
    #(MvPolynomial σ R) = max (max #R #σ) ℵ₀ := by 

Proof state:
σ R : Type u
inst✝² : CommSemiring R
inst✝¹ : Nonempty σ
inst✝ : Nontrivial R
⊢ #(MvPolynomial σ R) = max (max #R #σ) ℵ₀

Next tactic:
simp
/-- The cardinality of the multivariate polynomial ring, `MvPolynomial σ R` is at most the maximum
of `#R`, `#σ` and `ℵ₀` -/
theorem cardinal_mk_le_max : #(MvPolynomial σ R) ≤ max (max #R #σ) ℵ₀ :=
  cardinal_lift_mk_le_max.trans <| by 

Proof state:
σ R : Type u
inst✝ : CommSemiring R
⊢ max (max (lift.{u, u} #R) (lift.{u, u} #σ)) ℵ₀ ≤ max (max #R #σ) ℵ₀

Next tactic:
rw [lift_id, lift_id]
instance noZeroSMulDivisors {r : Semiring R} [AddCommMonoid M] [AddCommMonoid N]
    [Module R M] [Module R N] [NoZeroSMulDivisors R M] [NoZeroSMulDivisors R N] :
    NoZeroSMulDivisors R (M × N) :=
  { eq_zero_or_eq_zero_of_smul_eq_zero := by -- Porting note: in mathlib3 there is no need for `by`/
      -- `intro`/`exact`, i.e. the following works:
      -- ⟨fun c ⟨x, y⟩ h =>
      --   or_iff_not_imp_left.mpr fun hc =>
      

Proof state:
R : Type u_1
S : Type u_2
M : Type u_3
N : Type u_4
r : Semiring R
inst✝⁵ : AddCommMonoid M
inst✝⁴ : AddCommMonoid N
inst✝³ : Module R M
inst✝² : Module R N
inst✝¹ : NoZeroSMulDivisors R M
inst✝ : NoZeroSMulDivisors R N
⊢ ∀ {c : R} {x : M × N}, c • x = 0 → c = 0 ∨ x = 0

Next tactic:
intro c ⟨x, y⟩ h
instance noZeroSMulDivisors {r : Semiring R} [AddCommMonoid M] [AddCommMonoid N]
    [Module R M] [Module R N] [NoZeroSMulDivisors R M] [NoZeroSMulDivisors R N] :
    NoZeroSMulDivisors R (M × N) :=
  { eq_zero_or_eq_zero_of_smul_eq_zero := by -- Porting note: in mathlib3 there is no need for `by`/
      -- `intro`/`exact`, i.e. the following works:
      -- ⟨fun c ⟨x, y⟩ h =>
      --   or_iff_not_imp_left.mpr fun hc =>
      intro c ⟨x, y⟩ h
      

Proof state:
R : Type u_1
S : Type u_2
M : Type u_3
N : Type u_4
r : Semiring R
inst✝⁵ : AddCommMonoid M
inst✝⁴ : AddCommMonoid N
inst✝³ : Module R M
inst✝² : Module R N
inst✝¹ : NoZeroSMulDivisors R M
inst✝ : NoZeroSMulDivisors R N
c : R
x : M
y : N
h : c • (x, y) = 0
⊢ c = 0 ∨ (x, y) = 0

Next tactic:
exact or_iff_not_imp_left.mpr fun hc =>
        mk.inj_iff.mpr
          ⟨(smul_eq_zero.mp (congr_arg fst h)).resolve_left hc,
            (smul_eq_zero.mp (congr_arg snd h)).resolve_left hc⟩
/-- If `p` is a prime and `a` is an integer, then `a : ZMod p` is zero if and only if
`gcd a p ≠ 1`. -/
theorem eq_zero_iff_gcd_ne_one {a : ℤ} {p : ℕ} [pp : Fact p.Prime] :
    (a : ZMod p) = 0 ↔ a.gcd p ≠ 1 := by
  

Proof state:
a : ℤ
p : ℕ
pp : Fact (Nat.Prime p)
⊢ ↑a = 0 ↔ Int.gcd a ↑p ≠ 1

Next tactic:
rw [Ne, Int.gcd_comm, Int.gcd_eq_one_iff_coprime,
    (Nat.prime_iff_prime_int.1 pp.1).coprime_iff_not_dvd, Classical.not_not,
    int_cast_zmod_eq_zero_iff_dvd]
@[simp]
theorem zero'_eval : zero'.eval = fun v => pure (0 :: v) := by 

Proof state:
⊢ eval zero' = fun v => pure (0 :: v)

Next tactic:
simp [eval]
@[simp]
theorem succ_eval : succ.eval = fun v => pure [v.headI.succ] := by 

Proof state:
⊢ eval succ = fun v => pure [Nat.succ (List.headI v)]

Next tactic:
simp [eval]
@[simp]
theorem tail_eval : tail.eval = fun v => pure v.tail := by 

Proof state:
⊢ eval tail = fun v => pure (List.tail v)

Next tactic:
simp [eval]
@[simp]
theorem cons_eval (f fs) : (cons f fs).eval = fun v => do {
    let n ← Code.eval f v
    let ns ← Code.eval fs v
    pure (n.headI :: ns) } := by 

Proof state:
f fs : Code
⊢ eval (cons f fs) = fun v => do
    let n ← eval f v
    let ns ← eval fs v
    pure (List.headI n :: ns)

Next tactic:
simp [eval]
@[simp]
theorem comp_eval (f g) : (comp f g).eval = fun v => g.eval v >>= f.eval := by 

Proof state:
f g : Code
⊢ eval (comp f g) = fun v => eval g v >>= eval f

Next tactic:
simp [eval]
@[simp]
theorem case_eval (f g) :
    (case f g).eval = fun v => v.headI.rec (f.eval v.tail) fun y _ => g.eval (y::v.tail) := by
  

Proof state:
f g : Code
⊢ eval (case f g) = fun v => Nat.rec (eval f (List.tail v)) (fun y x => eval g (y :: List.tail v)) (List.headI v)

Next tactic:
simp [eval]
@[simp]
theorem fix_eval (f) : (fix f).eval =
    PFun.fix fun v => (f.eval v).map fun v =>
      if v.headI = 0 then Sum.inl v.tail else Sum.inr v.tail := by
  

Proof state:
f : Code
⊢ eval (fix f) =
    PFun.fix fun v =>
      Part.map (fun v => if List.headI v = 0 then Sum.inl (List.tail v) else Sum.inr (List.tail v)) (eval f v)

Next tactic:
simp [eval]
@[simp]
theorem nil_eval (v) : nil.eval v = pure [] := by 

Proof state:
v : List ℕ
⊢ eval nil v = pure []

Next tactic:
simp [nil]
@[simp]
theorem id_eval (v) : id.eval v = pure v := by 

Proof state:
v : List ℕ
⊢ eval id v = pure v

Next tactic:
simp [id]
@[simp]
theorem head_eval (v) : head.eval v = pure [v.headI] := by 

Proof state:
v : List ℕ
⊢ eval head v = pure [List.headI v]

Next tactic:
simp [head]
@[simp]
theorem zero_eval (v) : zero.eval v = pure [0] := by 

Proof state:
v : List ℕ
⊢ eval zero v = pure [0]

Next tactic:
simp [zero]
@[simp]
theorem pred_eval (v) : pred.eval v = pure [v.headI.pred] := by
  

Proof state:
v : List ℕ
⊢ eval pred v = pure [Nat.pred (List.headI v)]

Next tactic:
simp [pred]
@[simp]
theorem pred_eval (v) : pred.eval v = pure [v.headI.pred] := by
  simp [pred]; 

Proof state:
v : List ℕ
⊢ Nat.rec (Part.some [0]) (fun y x => Part.some [y]) (List.headI v) = Part.some [Nat.pred (List.headI v)]

Next tactic:
cases v.headI
@[simp]
theorem pred_eval (v) : pred.eval v = pure [v.headI.pred] := by
  simp [pred]; cases v.headI <;> 

Proof state:
case zero
v : List ℕ
⊢ Nat.rec (Part.some [0]) (fun y x => Part.some [y]) Nat.zero = Part.some [Nat.pred Nat.zero]

Next tactic:
simp
@[simp]
theorem pred_eval (v) : pred.eval v = pure [v.headI.pred] := by
  simp [pred]; cases v.headI <;> 

Proof state:
case succ
v : List ℕ
n✝ : ℕ
⊢ Nat.rec (Part.some [0]) (fun y x => Part.some [y]) (Nat.succ n✝) = Part.some [Nat.pred (Nat.succ n✝)]

Next tactic:
simp
theorem exists_code.comp {m n} {f : Vector ℕ n →. ℕ} {g : Fin n → Vector ℕ m →. ℕ}
    (hf : ∃ c : Code, ∀ v : Vector ℕ n, c.eval v.1 = pure <$> f v)
    (hg : ∀ i, ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> g i v) :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> ((Vector.mOfFn fun i => g i v) >>= f) := by
  

Proof state:
m n : ℕ
f : Vector ℕ n →. ℕ
g : Fin n → Vector ℕ m →. ℕ
hf : ∃ c, ∀ (v : Vector ℕ n), eval c ↑v = pure <$> f v
hg : ∀ (i : Fin n), ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> g i v
⊢ ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> ((Vector.mOfFn fun i => g i v) >>= f)

Next tactic:
rsuffices ⟨cg, hg⟩ :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = Subtype.val <$> Vector.mOfFn fun i => g i v
theorem exists_code.comp {m n} {f : Vector ℕ n →. ℕ} {g : Fin n → Vector ℕ m →. ℕ}
    (hf : ∃ c : Code, ∀ v : Vector ℕ n, c.eval v.1 = pure <$> f v)
    (hg : ∀ i, ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> g i v) :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> ((Vector.mOfFn fun i => g i v) >>= f) := by
  rsuffices ⟨cg, hg⟩ :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = Subtype.val <$> Vector.mOfFn fun i => g i v
  · 

Proof state:
case intro
m n : ℕ
f : Vector ℕ n →. ℕ
g : Fin n → Vector ℕ m →. ℕ
hf : ∃ c, ∀ (v : Vector ℕ n), eval c ↑v = pure <$> f v
hg✝ : ∀ (i : Fin n), ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> g i v
cg : Code
hg : ∀ (v : Vector ℕ m), eval cg ↑v = Subtype.val <$> Vector.mOfFn fun i => g i v
⊢ ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> ((Vector.mOfFn fun i => g i v) >>= f)

Next tactic:
obtain ⟨cf, hf⟩ := hf
theorem exists_code.comp {m n} {f : Vector ℕ n →. ℕ} {g : Fin n → Vector ℕ m →. ℕ}
    (hf : ∃ c : Code, ∀ v : Vector ℕ n, c.eval v.1 = pure <$> f v)
    (hg : ∀ i, ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> g i v) :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> ((Vector.mOfFn fun i => g i v) >>= f) := by
  rsuffices ⟨cg, hg⟩ :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = Subtype.val <$> Vector.mOfFn fun i => g i v
  · obtain ⟨cf, hf⟩ := hf
    

Proof state:
case intro.intro
m n : ℕ
f : Vector ℕ n →. ℕ
g : Fin n → Vector ℕ m →. ℕ
hg✝ : ∀ (i : Fin n), ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> g i v
cg : Code
hg : ∀ (v : Vector ℕ m), eval cg ↑v = Subtype.val <$> Vector.mOfFn fun i => g i v
cf : Code
hf : ∀ (v : Vector ℕ n), eval cf ↑v = pure <$> f v
⊢ ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> ((Vector.mOfFn fun i => g i v) >>= f)

Next tactic:
exact
      ⟨cf.comp cg, fun v => by
        simp [hg, hf, map_bind, seq_bind_eq, Function.comp]
        rfl⟩
theorem exists_code.comp {m n} {f : Vector ℕ n →. ℕ} {g : Fin n → Vector ℕ m →. ℕ}
    (hf : ∃ c : Code, ∀ v : Vector ℕ n, c.eval v.1 = pure <$> f v)
    (hg : ∀ i, ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> g i v) :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> ((Vector.mOfFn fun i => g i v) >>= f) := by
  rsuffices ⟨cg, hg⟩ :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = Subtype.val <$> Vector.mOfFn fun i => g i v
  · obtain ⟨cf, hf⟩ := hf
    exact
      ⟨cf.comp cg, fun v => by
        

Proof state:
m n : ℕ
f : Vector ℕ n →. ℕ
g : Fin n → Vector ℕ m →. ℕ
hg✝ : ∀ (i : Fin n), ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> g i v
cg : Code
hg : ∀ (v : Vector ℕ m), eval cg ↑v = Subtype.val <$> Vector.mOfFn fun i => g i v
cf : Code
hf : ∀ (v : Vector ℕ n), eval cf ↑v = pure <$> f v
v : Vector ℕ m
⊢ eval (Code.comp cf cg) ↑v = pure <$> ((Vector.mOfFn fun i => g i v) >>= f)

Next tactic:
simp [hg, hf, map_bind, seq_bind_eq, Function.comp]
theorem exists_code.comp {m n} {f : Vector ℕ n →. ℕ} {g : Fin n → Vector ℕ m →. ℕ}
    (hf : ∃ c : Code, ∀ v : Vector ℕ n, c.eval v.1 = pure <$> f v)
    (hg : ∀ i, ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> g i v) :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> ((Vector.mOfFn fun i => g i v) >>= f) := by
  rsuffices ⟨cg, hg⟩ :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = Subtype.val <$> Vector.mOfFn fun i => g i v
  · obtain ⟨cf, hf⟩ := hf
    exact
      ⟨cf.comp cg, fun v => by
        simp [hg, hf, map_bind, seq_bind_eq, Function.comp]
        

Proof state:
m n : ℕ
f : Vector ℕ n →. ℕ
g : Fin n → Vector ℕ m →. ℕ
hg✝ : ∀ (i : Fin n), ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> g i v
cg : Code
hg : ∀ (v : Vector ℕ m), eval cg ↑v = Subtype.val <$> Vector.mOfFn fun i => g i v
cf : Code
hf : ∀ (v : Vector ℕ n), eval cf ↑v = pure <$> f v
v : Vector ℕ m
⊢ (do
      let x ← Vector.mOfFn fun i => g i v
      pure <$> f x) =
    do
    let a ← Vector.mOfFn fun i => g i v
    pure <$> f a

Next tactic:
rfl
theorem exists_code.comp {m n} {f : Vector ℕ n →. ℕ} {g : Fin n → Vector ℕ m →. ℕ}
    (hf : ∃ c : Code, ∀ v : Vector ℕ n, c.eval v.1 = pure <$> f v)
    (hg : ∀ i, ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> g i v) :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> ((Vector.mOfFn fun i => g i v) >>= f) := by
  rsuffices ⟨cg, hg⟩ :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = Subtype.val <$> Vector.mOfFn fun i => g i v
  · obtain ⟨cf, hf⟩ := hf
    exact
      ⟨cf.comp cg, fun v => by
        simp [hg, hf, map_bind, seq_bind_eq, Function.comp]
        rfl⟩
  

Proof state:
m n : ℕ
f : Vector ℕ n →. ℕ
g : Fin n → Vector ℕ m →. ℕ
hf : ∃ c, ∀ (v : Vector ℕ n), eval c ↑v = pure <$> f v
hg : ∀ (i : Fin n), ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> g i v
⊢ ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = Subtype.val <$> Vector.mOfFn fun i => g i v

Next tactic:
clear hf f
theorem exists_code.comp {m n} {f : Vector ℕ n →. ℕ} {g : Fin n → Vector ℕ m →. ℕ}
    (hf : ∃ c : Code, ∀ v : Vector ℕ n, c.eval v.1 = pure <$> f v)
    (hg : ∀ i, ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> g i v) :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> ((Vector.mOfFn fun i => g i v) >>= f) := by
  rsuffices ⟨cg, hg⟩ :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = Subtype.val <$> Vector.mOfFn fun i => g i v
  · obtain ⟨cf, hf⟩ := hf
    exact
      ⟨cf.comp cg, fun v => by
        simp [hg, hf, map_bind, seq_bind_eq, Function.comp]
        rfl⟩
  clear hf f; 

Proof state:
m n : ℕ
g : Fin n → Vector ℕ m →. ℕ
hg : ∀ (i : Fin n), ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> g i v
⊢ ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = Subtype.val <$> Vector.mOfFn fun i => g i v

Next tactic:
induction' n with n IH
theorem exists_code.comp {m n} {f : Vector ℕ n →. ℕ} {g : Fin n → Vector ℕ m →. ℕ}
    (hf : ∃ c : Code, ∀ v : Vector ℕ n, c.eval v.1 = pure <$> f v)
    (hg : ∀ i, ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> g i v) :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> ((Vector.mOfFn fun i => g i v) >>= f) := by
  rsuffices ⟨cg, hg⟩ :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = Subtype.val <$> Vector.mOfFn fun i => g i v
  · obtain ⟨cf, hf⟩ := hf
    exact
      ⟨cf.comp cg, fun v => by
        simp [hg, hf, map_bind, seq_bind_eq, Function.comp]
        rfl⟩
  clear hf f; induction' n with n IH
  · 

Proof state:
case zero
m : ℕ
g : Fin Nat.zero → Vector ℕ m →. ℕ
hg : ∀ (i : Fin Nat.zero), ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> g i v
⊢ ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = Subtype.val <$> Vector.mOfFn fun i => g i v

Next tactic:
exact ⟨nil, fun v => by simp [Vector.mOfFn, Bind.bind]; rfl⟩
theorem exists_code.comp {m n} {f : Vector ℕ n →. ℕ} {g : Fin n → Vector ℕ m →. ℕ}
    (hf : ∃ c : Code, ∀ v : Vector ℕ n, c.eval v.1 = pure <$> f v)
    (hg : ∀ i, ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> g i v) :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> ((Vector.mOfFn fun i => g i v) >>= f) := by
  rsuffices ⟨cg, hg⟩ :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = Subtype.val <$> Vector.mOfFn fun i => g i v
  · obtain ⟨cf, hf⟩ := hf
    exact
      ⟨cf.comp cg, fun v => by
        simp [hg, hf, map_bind, seq_bind_eq, Function.comp]
        rfl⟩
  clear hf f; induction' n with n IH
  · exact ⟨nil, fun v => by 

Proof state:
m : ℕ
g : Fin Nat.zero → Vector ℕ m →. ℕ
hg : ∀ (i : Fin Nat.zero), ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> g i v
v : Vector ℕ m
⊢ eval nil ↑v = Subtype.val <$> Vector.mOfFn fun i => g i v

Next tactic:
simp [Vector.mOfFn, Bind.bind]
theorem exists_code.comp {m n} {f : Vector ℕ n →. ℕ} {g : Fin n → Vector ℕ m →. ℕ}
    (hf : ∃ c : Code, ∀ v : Vector ℕ n, c.eval v.1 = pure <$> f v)
    (hg : ∀ i, ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> g i v) :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> ((Vector.mOfFn fun i => g i v) >>= f) := by
  rsuffices ⟨cg, hg⟩ :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = Subtype.val <$> Vector.mOfFn fun i => g i v
  · obtain ⟨cf, hf⟩ := hf
    exact
      ⟨cf.comp cg, fun v => by
        simp [hg, hf, map_bind, seq_bind_eq, Function.comp]
        rfl⟩
  clear hf f; induction' n with n IH
  · exact ⟨nil, fun v => by simp [Vector.mOfFn, Bind.bind]; 

Proof state:
m : ℕ
g : Fin Nat.zero → Vector ℕ m →. ℕ
hg : ∀ (i : Fin Nat.zero), ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> g i v
v : Vector ℕ m
⊢ Part.some [] = Subtype.val <$> Part.some Vector.nil

Next tactic:
rfl
theorem exists_code.comp {m n} {f : Vector ℕ n →. ℕ} {g : Fin n → Vector ℕ m →. ℕ}
    (hf : ∃ c : Code, ∀ v : Vector ℕ n, c.eval v.1 = pure <$> f v)
    (hg : ∀ i, ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> g i v) :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> ((Vector.mOfFn fun i => g i v) >>= f) := by
  rsuffices ⟨cg, hg⟩ :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = Subtype.val <$> Vector.mOfFn fun i => g i v
  · obtain ⟨cf, hf⟩ := hf
    exact
      ⟨cf.comp cg, fun v => by
        simp [hg, hf, map_bind, seq_bind_eq, Function.comp]
        rfl⟩
  clear hf f; induction' n with n IH
  · exact ⟨nil, fun v => by simp [Vector.mOfFn, Bind.bind]; rfl⟩
  · 

Proof state:
case succ
m n : ℕ
IH :
  ∀ {g : Fin n → Vector ℕ m →. ℕ},
    (∀ (i : Fin n), ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> g i v) →
      ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = Subtype.val <$> Vector.mOfFn fun i => g i v
g : Fin (Nat.succ n) → Vector ℕ m →. ℕ
hg : ∀ (i : Fin (Nat.succ n)), ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> g i v
⊢ ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = Subtype.val <$> Vector.mOfFn fun i => g i v

Next tactic:
obtain ⟨cg, hg₁⟩ := hg 0
theorem exists_code.comp {m n} {f : Vector ℕ n →. ℕ} {g : Fin n → Vector ℕ m →. ℕ}
    (hf : ∃ c : Code, ∀ v : Vector ℕ n, c.eval v.1 = pure <$> f v)
    (hg : ∀ i, ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> g i v) :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> ((Vector.mOfFn fun i => g i v) >>= f) := by
  rsuffices ⟨cg, hg⟩ :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = Subtype.val <$> Vector.mOfFn fun i => g i v
  · obtain ⟨cf, hf⟩ := hf
    exact
      ⟨cf.comp cg, fun v => by
        simp [hg, hf, map_bind, seq_bind_eq, Function.comp]
        rfl⟩
  clear hf f; induction' n with n IH
  · exact ⟨nil, fun v => by simp [Vector.mOfFn, Bind.bind]; rfl⟩
  · obtain ⟨cg, hg₁⟩ := hg 0
    

Proof state:
case succ.intro
m n : ℕ
IH :
  ∀ {g : Fin n → Vector ℕ m →. ℕ},
    (∀ (i : Fin n), ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> g i v) →
      ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = Subtype.val <$> Vector.mOfFn fun i => g i v
g : Fin (Nat.succ n) → Vector ℕ m →. ℕ
hg : ∀ (i : Fin (Nat.succ n)), ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> g i v
cg : Code
hg₁ : ∀ (v : Vector ℕ m), eval cg ↑v = pure <$> g 0 v
⊢ ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = Subtype.val <$> Vector.mOfFn fun i => g i v

Next tactic:
obtain ⟨cl, hl⟩ := IH fun i => hg i.succ
theorem exists_code.comp {m n} {f : Vector ℕ n →. ℕ} {g : Fin n → Vector ℕ m →. ℕ}
    (hf : ∃ c : Code, ∀ v : Vector ℕ n, c.eval v.1 = pure <$> f v)
    (hg : ∀ i, ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> g i v) :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> ((Vector.mOfFn fun i => g i v) >>= f) := by
  rsuffices ⟨cg, hg⟩ :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = Subtype.val <$> Vector.mOfFn fun i => g i v
  · obtain ⟨cf, hf⟩ := hf
    exact
      ⟨cf.comp cg, fun v => by
        simp [hg, hf, map_bind, seq_bind_eq, Function.comp]
        rfl⟩
  clear hf f; induction' n with n IH
  · exact ⟨nil, fun v => by simp [Vector.mOfFn, Bind.bind]; rfl⟩
  · obtain ⟨cg, hg₁⟩ := hg 0
    obtain ⟨cl, hl⟩ := IH fun i => hg i.succ
    

Proof state:
case succ.intro.intro
m n : ℕ
IH :
  ∀ {g : Fin n → Vector ℕ m →. ℕ},
    (∀ (i : Fin n), ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> g i v) →
      ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = Subtype.val <$> Vector.mOfFn fun i => g i v
g : Fin (Nat.succ n) → Vector ℕ m →. ℕ
hg : ∀ (i : Fin (Nat.succ n)), ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> g i v
cg : Code
hg₁ : ∀ (v : Vector ℕ m), eval cg ↑v = pure <$> g 0 v
cl : Code
hl : ∀ (v : Vector ℕ m), eval cl ↑v = Subtype.val <$> Vector.mOfFn fun i => g (Fin.succ i) v
⊢ ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = Subtype.val <$> Vector.mOfFn fun i => g i v

Next tactic:
exact
      ⟨cons cg cl, fun v => by
        simp [Vector.mOfFn, hg₁, map_bind, seq_bind_eq, bind_assoc, (· ∘ ·), hl]
        rfl⟩
theorem exists_code.comp {m n} {f : Vector ℕ n →. ℕ} {g : Fin n → Vector ℕ m →. ℕ}
    (hf : ∃ c : Code, ∀ v : Vector ℕ n, c.eval v.1 = pure <$> f v)
    (hg : ∀ i, ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> g i v) :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> ((Vector.mOfFn fun i => g i v) >>= f) := by
  rsuffices ⟨cg, hg⟩ :
    ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = Subtype.val <$> Vector.mOfFn fun i => g i v
  · obtain ⟨cf, hf⟩ := hf
    exact
      ⟨cf.comp cg, fun v => by
        simp [hg, hf, map_bind, seq_bind_eq, Function.comp]
        rfl⟩
  clear hf f; induction' n with n IH
  · exact ⟨nil, fun v => by simp [Vector.mOfFn, Bind.bind]; rfl⟩
  · obtain ⟨cg, hg₁⟩ := hg 0
    obtain ⟨cl, hl⟩ := IH fun i => hg i.succ
    exact
      ⟨cons cg cl, fun v => by
        

Proof state:
m n : ℕ
IH :
  ∀ {g : Fin n → Vector ℕ m →. ℕ},
    (∀ (i : Fin n), ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> g i v) →
      ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = Subtype.val <$> Vector.mOfFn fun i => g i v
g : Fin (Nat.succ n) → Vector ℕ m →. ℕ
hg : ∀ (i : Fin (Nat.succ n)), ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> g i v
cg : Code
hg₁ : ∀ (v : Vector ℕ m), eval cg ↑v = pure <$> g 0 v
cl : Code
hl : ∀ (v : Vector ℕ m), eval cl ↑v = Subtype.val <$> Vector.mOfFn fun i => g (Fin.succ i) v
v : Vector ℕ m
⊢ eval (cons cg cl) ↑v = Subtype.val <$> Vector.mOfFn fun i => g i v

Next tactic:
simp [Vector.mOfFn, hg₁, map_bind, seq_bind_eq, bind_assoc, (· ∘ ·), hl]