l3lab/ntp-mathlib huggingface dataset:
theorem interpolate_eq_of_values_eq_on (hrr' : ∀ i ∈ s, r i = r' i) :
    interpolate s v r = interpolate s v r' :=
  sum_congr rfl fun i hi => by 

Proof state:
F : Type u_1
inst✝¹ : Field F
ι : Type u_2
inst✝ : DecidableEq ι
s t : Finset ι
i✝ j : ι
v r r' : ι → F
hrr' : ∀ i ∈ s, r i = r' i
i : ι
hi : i ∈ s
⊢ C (r i) * Lagrange.basis s v i = C (r' i) * Lagrange.basis s v i

Next tactic:
rw [hrr' _ hi]
theorem eq_interpolate_of_eval_eq {f : F[X]} (hvs : Set.InjOn v s) (degree_f_lt : f.degree < s.card)
    (eval_f : ∀ i ∈ s, f.eval (v i) = r i) : f = interpolate s v r := by
  

Proof state:
F : Type u_1
inst✝¹ : Field F
ι : Type u_2
inst✝ : DecidableEq ι
s t : Finset ι
i j : ι
v r r' : ι → F
f : F[X]
hvs : Set.InjOn v ↑s
degree_f_lt : degree f < ↑(card s)
eval_f : ∀ i ∈ s, eval (v i) f = r i
⊢ f = (interpolate s v) r

Next tactic:
rw [eq_interpolate hvs degree_f_lt]
theorem eq_interpolate_of_eval_eq {f : F[X]} (hvs : Set.InjOn v s) (degree_f_lt : f.degree < s.card)
    (eval_f : ∀ i ∈ s, f.eval (v i) = r i) : f = interpolate s v r := by
  rw [eq_interpolate hvs degree_f_lt]
  

Proof state:
F : Type u_1
inst✝¹ : Field F
ι : Type u_2
inst✝ : DecidableEq ι
s t : Finset ι
i j : ι
v r r' : ι → F
f : F[X]
hvs : Set.InjOn v ↑s
degree_f_lt : degree f < ↑(card s)
eval_f : ∀ i ∈ s, eval (v i) f = r i
⊢ ((interpolate s v) fun i => eval (v i) f) = (interpolate s v) r

Next tactic:
exact interpolate_eq_of_values_eq_on _ _ eval_f
/-- This is the characteristic property of the interpolation: the interpolation is the
unique polynomial of `degree < Fintype.card ι` which takes the value of the `r i` on the `v i`.
-/
theorem eq_interpolate_iff {f : F[X]} (hvs : Set.InjOn v s) :
    (f.degree < s.card ∧ ∀ i ∈ s, eval (v i) f = r i) ↔ f = interpolate s v r := by
  

Proof state:
F : Type u_1
inst✝¹ : Field F
ι : Type u_2
inst✝ : DecidableEq ι
s t : Finset ι
i j : ι
v r r' : ι → F
f : F[X]
hvs : Set.InjOn v ↑s
⊢ (degree f < ↑(card s) ∧ ∀ i ∈ s, eval (v i) f = r i) ↔ f = (interpolate s v) r

Next tactic:
constructor
/-- This is the characteristic property of the interpolation: the interpolation is the
unique polynomial of `degree < Fintype.card ι` which takes the value of the `r i` on the `v i`.
-/
theorem eq_interpolate_iff {f : F[X]} (hvs : Set.InjOn v s) :
    (f.degree < s.card ∧ ∀ i ∈ s, eval (v i) f = r i) ↔ f = interpolate s v r := by
  constructor <;> 

Proof state:
case mp
F : Type u_1
inst✝¹ : Field F
ι : Type u_2
inst✝ : DecidableEq ι
s t : Finset ι
i j : ι
v r r' : ι → F
f : F[X]
hvs : Set.InjOn v ↑s
⊢ (degree f < ↑(card s) ∧ ∀ i ∈ s, eval (v i) f = r i) → f = (interpolate s v) r

Next tactic:
intro h
/-- This is the characteristic property of the interpolation: the interpolation is the
unique polynomial of `degree < Fintype.card ι` which takes the value of the `r i` on the `v i`.
-/
theorem eq_interpolate_iff {f : F[X]} (hvs : Set.InjOn v s) :
    (f.degree < s.card ∧ ∀ i ∈ s, eval (v i) f = r i) ↔ f = interpolate s v r := by
  constructor <;> 

Proof state:
case mpr
F : Type u_1
inst✝¹ : Field F
ι : Type u_2
inst✝ : DecidableEq ι
s t : Finset ι
i j : ι
v r r' : ι → F
f : F[X]
hvs : Set.InjOn v ↑s
⊢ f = (interpolate s v) r → degree f < ↑(card s) ∧ ∀ i ∈ s, eval (v i) f = r i

Next tactic:
intro h
/-- This is the characteristic property of the interpolation: the interpolation is the
unique polynomial of `degree < Fintype.card ι` which takes the value of the `r i` on the `v i`.
-/
theorem eq_interpolate_iff {f : F[X]} (hvs : Set.InjOn v s) :
    (f.degree < s.card ∧ ∀ i ∈ s, eval (v i) f = r i) ↔ f = interpolate s v r := by
  constructor <;> intro h
  · 

Proof state:
case mp
F : Type u_1
inst✝¹ : Field F
ι : Type u_2
inst✝ : DecidableEq ι
s t : Finset ι
i j : ι
v r r' : ι → F
f : F[X]
hvs : Set.InjOn v ↑s
h : degree f < ↑(card s) ∧ ∀ i ∈ s, eval (v i) f = r i
⊢ f = (interpolate s v) r

Next tactic:
exact eq_interpolate_of_eval_eq _ hvs h.1 h.2
/-- This is the characteristic property of the interpolation: the interpolation is the
unique polynomial of `degree < Fintype.card ι` which takes the value of the `r i` on the `v i`.
-/
theorem eq_interpolate_iff {f : F[X]} (hvs : Set.InjOn v s) :
    (f.degree < s.card ∧ ∀ i ∈ s, eval (v i) f = r i) ↔ f = interpolate s v r := by
  constructor <;> intro h
  · exact eq_interpolate_of_eval_eq _ hvs h.1 h.2
  · 

Proof state:
case mpr
F : Type u_1
inst✝¹ : Field F
ι : Type u_2
inst✝ : DecidableEq ι
s t : Finset ι
i j : ι
v r r' : ι → F
f : F[X]
hvs : Set.InjOn v ↑s
h : f = (interpolate s v) r
⊢ degree f < ↑(card s) ∧ ∀ i ∈ s, eval (v i) f = r i

Next tactic:
rw [h]
/-- This is the characteristic property of the interpolation: the interpolation is the
unique polynomial of `degree < Fintype.card ι` which takes the value of the `r i` on the `v i`.
-/
theorem eq_interpolate_iff {f : F[X]} (hvs : Set.InjOn v s) :
    (f.degree < s.card ∧ ∀ i ∈ s, eval (v i) f = r i) ↔ f = interpolate s v r := by
  constructor <;> intro h
  · exact eq_interpolate_of_eval_eq _ hvs h.1 h.2
  · rw [h]
    

Proof state:
case mpr
F : Type u_1
inst✝¹ : Field F
ι : Type u_2
inst✝ : DecidableEq ι
s t : Finset ι
i j : ι
v r r' : ι → F
f : F[X]
hvs : Set.InjOn v ↑s
h : f = (interpolate s v) r
⊢ degree ((interpolate s v) r) < ↑(card s) ∧ ∀ i ∈ s, eval (v i) ((interpolate s v) r) = r i

Next tactic:
exact ⟨degree_interpolate_lt _ hvs, fun _ hi => eval_interpolate_at_node _ hvs hi⟩
/-- Lagrange interpolation induces isomorphism between functions from `s`
and polynomials of degree less than `Fintype.card ι`.-/
def funEquivDegreeLT (hvs : Set.InjOn v s) : degreeLT F s.card ≃ₗ[F] s → F where
  toFun f i := f.1.eval (v i)
  map_add' f g := funext fun v => eval_add
  map_smul' c f := funext <| by 

Proof state:
F : Type u_1
inst✝¹ : Field F
ι : Type u_2
inst✝ : DecidableEq ι
s t : Finset ι
i j : ι
v r r' : ι → F
hvs : Set.InjOn v ↑s
c : F
f : ↥(degreeLT F (card s))
⊢ ∀ (x : { x // x ∈ s }),
    AddHom.toFun
        { toFun := fun f i => eval (v ↑i) ↑f,
          map_add' :=
            (_ :
              ∀ (f g : ↥(degreeLT F (card s))),
                (fun f i => eval (v ↑i) ↑f) (f + g) = (fun f i => eval (v ↑i) ↑f) f + (fun f i => eval (v ↑i) ↑f) g) }
        (c • f) x =
      ((RingHom.id F) c •
          AddHom.toFun
            { toFun := fun f i => eval (v ↑i) ↑f,
              map_add' :=
                (_ :
                  ∀ (f g : ↥(degreeLT F (card s))),
                    (fun f i => eval (v ↑i) ↑f) (f + g) =
                      (fun f i => eval (v ↑i) ↑f) f + (fun f i => eval (v ↑i) ↑f) g) }
            f)
        x

Next tactic:
simp
/-- Lagrange interpolation induces isomorphism between functions from `s`
and polynomials of degree less than `Fintype.card ι`.-/
def funEquivDegreeLT (hvs : Set.InjOn v s) : degreeLT F s.card ≃ₗ[F] s → F where
  toFun f i := f.1.eval (v i)
  map_add' f g := funext fun v => eval_add
  map_smul' c f := funext <| by simp
  invFun r :=
    ⟨interpolate s v fun x => if hx : x ∈ s then r ⟨x, hx⟩ else 0,
      mem_degreeLT.2 <| degree_interpolate_lt _ hvs⟩
  left_inv := by
    

Proof state:
F : Type u_1
inst✝¹ : Field F
ι : Type u_2
inst✝ : DecidableEq ι
s t : Finset ι
i j : ι
v r r' : ι → F
hvs : Set.InjOn v ↑s
⊢ Function.LeftInverse
    (fun r =>
      { val := (interpolate s v) fun x => if hx : x ∈ s then r { val := x, property := hx } else 0,
        property :=
          (_ :
            ((interpolate s v) fun x => if hx : x ∈ s then r { val := x, property := hx } else 0) ∈
              degreeLT F (card s)) })
    {
          toAddHom :=
            { toFun := fun f i => eval (v ↑i) ↑f,
              map_add' :=
                (_ :
                  ∀ (f g : ↥(degreeLT F (card s))),
                    (fun f i => eval (v ↑i) ↑f) (f + g) =
                      (fun f i => eval (v ↑i) ↑f) f + (fun f i => eval (v ↑i) ↑f) g) },
          map_smul' :=
            (_ :
              ∀ (c : F) (f : ↥(degreeLT F (card s))),
                AddHom.toFun
                    { toFun := fun f i => eval (v ↑i) ↑f,
                      map_add' :=
                        (_ :
                          ∀ (f g : ↥(degreeLT F (card s))),
                            (fun f i => eval (v ↑i) ↑f) (f + g) =
                              (fun f i => eval (v ↑i) ↑f) f + (fun f i => eval (v ↑i) ↑f) g) }
                    (c • f) =
                  (RingHom.id F) c •
                    AddHom.toFun
                      { toFun := fun f i => eval (v ↑i) ↑f,
                        map_add' :=
                          (_ :
                            ∀ (f g : ↥(degreeLT F (card s))),
                              (fun f i => eval (v ↑i) ↑f) (f + g) =
                                (fun f i => eval (v ↑i) ↑f) f + (fun f i => eval (v ↑i) ↑f) g) }
                      f) }.toAddHom.toFun

Next tactic:
rintro ⟨f, hf⟩
/-- Lagrange interpolation induces isomorphism between functions from `s`
and polynomials of degree less than `Fintype.card ι`.-/
def funEquivDegreeLT (hvs : Set.InjOn v s) : degreeLT F s.card ≃ₗ[F] s → F where
  toFun f i := f.1.eval (v i)
  map_add' f g := funext fun v => eval_add
  map_smul' c f := funext <| by simp
  invFun r :=
    ⟨interpolate s v fun x => if hx : x ∈ s then r ⟨x, hx⟩ else 0,
      mem_degreeLT.2 <| degree_interpolate_lt _ hvs⟩
  left_inv := by
    rintro ⟨f, hf⟩
    

Proof state:
case mk
F : Type u_1
inst✝¹ : Field F
ι : Type u_2
inst✝ : DecidableEq ι
s t : Finset ι
i j : ι
v r r' : ι → F
hvs : Set.InjOn v ↑s
f : F[X]
hf : f ∈ degreeLT F (card s)
⊢ (fun r =>
        { val := (interpolate s v) fun x => if hx : x ∈ s then r { val := x, property := hx } else 0,
          property :=
            (_ :
              ((interpolate s v) fun x => if hx : x ∈ s then r { val := x, property := hx } else 0) ∈
                degreeLT F (card s)) })
      (AddHom.toFun
        {
            toAddHom :=
              { toFun := fun f i => eval (v ↑i) ↑f,
                map_add' :=
                  (_ :
                    ∀ (f g : ↥(degreeLT F (card s))),
                      (fun f i => eval (v ↑i) ↑f) (f + g) =
                        (fun f i => eval (v ↑i) ↑f) f + (fun f i => eval (v ↑i) ↑f) g) },
            map_smul' :=
              (_ :
                ∀ (c : F) (f : ↥(degreeLT F (card s))),
                  AddHom.toFun
                      { toFun := fun f i => eval (v ↑i) ↑f,
                        map_add' :=
                          (_ :
                            ∀ (f g : ↥(degreeLT F (card s))),
                              (fun f i => eval (v ↑i) ↑f) (f + g) =
                                (fun f i => eval (v ↑i) ↑f) f + (fun f i => eval (v ↑i) ↑f) g) }
                      (c • f) =
                    (RingHom.id F) c •
                      AddHom.toFun
                        { toFun := fun f i => eval (v ↑i) ↑f,
                          map_add' :=
                            (_ :
                              ∀ (f g : ↥(degreeLT F (card s))),
                                (fun f i => eval (v ↑i) ↑f) (f + g) =
                                  (fun f i => eval (v ↑i) ↑f) f + (fun f i => eval (v ↑i) ↑f) g) }
                        f) }.toAddHom
        { val := f, property := hf }) =
    { val := f, property := hf }

Next tactic:
simp only [Subtype.mk_eq_mk, Subtype.coe_mk, dite_eq_ite]
/-- Lagrange interpolation induces isomorphism between functions from `s`
and polynomials of degree less than `Fintype.card ι`.-/
def funEquivDegreeLT (hvs : Set.InjOn v s) : degreeLT F s.card ≃ₗ[F] s → F where
  toFun f i := f.1.eval (v i)
  map_add' f g := funext fun v => eval_add
  map_smul' c f := funext <| by simp
  invFun r :=
    ⟨interpolate s v fun x => if hx : x ∈ s then r ⟨x, hx⟩ else 0,
      mem_degreeLT.2 <| degree_interpolate_lt _ hvs⟩
  left_inv := by
    rintro ⟨f, hf⟩
    simp only [Subtype.mk_eq_mk, Subtype.coe_mk, dite_eq_ite]
    

Proof state:
case mk
F : Type u_1
inst✝¹ : Field F
ι : Type u_2
inst✝ : DecidableEq ι
s t : Finset ι
i j : ι
v r r' : ι → F
hvs : Set.InjOn v ↑s
f : F[X]
hf : f ∈ degreeLT F (card s)
⊢ ((interpolate s v) fun x => if x ∈ s then eval (v x) f else 0) = f

Next tactic:
rw [mem_degreeLT] at hf
/-- Lagrange interpolation induces isomorphism between functions from `s`
and polynomials of degree less than `Fintype.card ι`.-/
def funEquivDegreeLT (hvs : Set.InjOn v s) : degreeLT F s.card ≃ₗ[F] s → F where
  toFun f i := f.1.eval (v i)
  map_add' f g := funext fun v => eval_add
  map_smul' c f := funext <| by simp
  invFun r :=
    ⟨interpolate s v fun x => if hx : x ∈ s then r ⟨x, hx⟩ else 0,
      mem_degreeLT.2 <| degree_interpolate_lt _ hvs⟩
  left_inv := by
    rintro ⟨f, hf⟩
    simp only [Subtype.mk_eq_mk, Subtype.coe_mk, dite_eq_ite]
    rw [mem_degreeLT] at hf
    

Proof state:
case mk
F : Type u_1
inst✝¹ : Field F
ι : Type u_2
inst✝ : DecidableEq ι
s t : Finset ι
i j : ι
v r r' : ι → F
hvs : Set.InjOn v ↑s
f : F[X]
hf : degree f < ↑(card s)
⊢ ((interpolate s v) fun x => if x ∈ s then eval (v x) f else 0) = f

Next tactic:
conv => rhs; rw [eq_interpolate hvs hf]
/-- Lagrange interpolation induces isomorphism between functions from `s`
and polynomials of degree less than `Fintype.card ι`.-/
def funEquivDegreeLT (hvs : Set.InjOn v s) : degreeLT F s.card ≃ₗ[F] s → F where
  toFun f i := f.1.eval (v i)
  map_add' f g := funext fun v => eval_add
  map_smul' c f := funext <| by simp
  invFun r :=
    ⟨interpolate s v fun x => if hx : x ∈ s then r ⟨x, hx⟩ else 0,
      mem_degreeLT.2 <| degree_interpolate_lt _ hvs⟩
  left_inv := by
    rintro ⟨f, hf⟩
    simp only [Subtype.mk_eq_mk, Subtype.coe_mk, dite_eq_ite]
    rw [mem_degreeLT] at hf
    conv => 

Proof state:
F : Type u_1
inst✝¹ : Field F
ι : Type u_2
inst✝ : DecidableEq ι
s t : Finset ι
i j : ι
v r r' : ι → F
hvs : Set.InjOn v ↑s
f : F[X]
hf : degree f < ↑(card s)
| ((interpolate s v) fun x => if x ∈ s then eval (v x) f else 0) = f

Next tactic:
rhs; rw [eq_interpolate hvs hf]
/-- Lagrange interpolation induces isomorphism between functions from `s`
and polynomials of degree less than `Fintype.card ι`.-/
def funEquivDegreeLT (hvs : Set.InjOn v s) : degreeLT F s.card ≃ₗ[F] s → F where
  toFun f i := f.1.eval (v i)
  map_add' f g := funext fun v => eval_add
  map_smul' c f := funext <| by simp
  invFun r :=
    ⟨interpolate s v fun x => if hx : x ∈ s then r ⟨x, hx⟩ else 0,
      mem_degreeLT.2 <| degree_interpolate_lt _ hvs⟩
  left_inv := by
    rintro ⟨f, hf⟩
    simp only [Subtype.mk_eq_mk, Subtype.coe_mk, dite_eq_ite]
    rw [mem_degreeLT] at hf
    conv => 

Proof state:
F : Type u_1
inst✝¹ : Field F
ι : Type u_2
inst✝ : DecidableEq ι
s t : Finset ι
i j : ι
v r r' : ι → F
hvs : Set.InjOn v ↑s
f : F[X]
hf : degree f < ↑(card s)
| ((interpolate s v) fun x => if x ∈ s then eval (v x) f else 0) = f

Next tactic:
rhs
/-- Lagrange interpolation induces isomorphism between functions from `s`
and polynomials of degree less than `Fintype.card ι`.-/
def funEquivDegreeLT (hvs : Set.InjOn v s) : degreeLT F s.card ≃ₗ[F] s → F where
  toFun f i := f.1.eval (v i)
  map_add' f g := funext fun v => eval_add
  map_smul' c f := funext <| by simp
  invFun r :=
    ⟨interpolate s v fun x => if hx : x ∈ s then r ⟨x, hx⟩ else 0,
      mem_degreeLT.2 <| degree_interpolate_lt _ hvs⟩
  left_inv := by
    rintro ⟨f, hf⟩
    simp only [Subtype.mk_eq_mk, Subtype.coe_mk, dite_eq_ite]
    rw [mem_degreeLT] at hf
    conv => rhs; 

Proof state:
F : Type u_1
inst✝¹ : Field F
ι : Type u_2
inst✝ : DecidableEq ι
s t : Finset ι
i j : ι
v r r' : ι → F
hvs : Set.InjOn v ↑s
f : F[X]
hf : degree f < ↑(card s)
| f

Next tactic:
rw [eq_interpolate hvs hf]
/-- Lagrange interpolation induces isomorphism between functions from `s`
and polynomials of degree less than `Fintype.card ι`.-/
def funEquivDegreeLT (hvs : Set.InjOn v s) : degreeLT F s.card ≃ₗ[F] s → F where
  toFun f i := f.1.eval (v i)
  map_add' f g := funext fun v => eval_add
  map_smul' c f := funext <| by simp
  invFun r :=
    ⟨interpolate s v fun x => if hx : x ∈ s then r ⟨x, hx⟩ else 0,
      mem_degreeLT.2 <| degree_interpolate_lt _ hvs⟩
  left_inv := by
    rintro ⟨f, hf⟩
    simp only [Subtype.mk_eq_mk, Subtype.coe_mk, dite_eq_ite]
    rw [mem_degreeLT] at hf
    conv => rhs; rw [eq_interpolate hvs hf]
    

Proof state:
case mk
F : Type u_1
inst✝¹ : Field F
ι : Type u_2
inst✝ : DecidableEq ι
s t : Finset ι
i j : ι
v r r' : ι → F
hvs : Set.InjOn v ↑s
f : F[X]
hf : degree f < ↑(card s)
⊢ ((interpolate s v) fun x => if x ∈ s then eval (v x) f else 0) = (interpolate s v) fun i => eval (v i) f

Next tactic:
exact interpolate_eq_of_values_eq_on _ _ fun _ hi => if_pos hi
/-- Lagrange interpolation induces isomorphism between functions from `s`
and polynomials of degree less than `Fintype.card ι`.-/
def funEquivDegreeLT (hvs : Set.InjOn v s) : degreeLT F s.card ≃ₗ[F] s → F where
  toFun f i := f.1.eval (v i)
  map_add' f g := funext fun v => eval_add
  map_smul' c f := funext <| by simp
  invFun r :=
    ⟨interpolate s v fun x => if hx : x ∈ s then r ⟨x, hx⟩ else 0,
      mem_degreeLT.2 <| degree_interpolate_lt _ hvs⟩
  left_inv := by
    rintro ⟨f, hf⟩
    simp only [Subtype.mk_eq_mk, Subtype.coe_mk, dite_eq_ite]
    rw [mem_degreeLT] at hf
    conv => rhs; rw [eq_interpolate hvs hf]
    exact interpolate_eq_of_values_eq_on _ _ fun _ hi => if_pos hi
  right_inv := by
    

Proof state:
F : Type u_1
inst✝¹ : Field F
ι : Type u_2
inst✝ : DecidableEq ι
s t : Finset ι
i j : ι
v r r' : ι → F
hvs : Set.InjOn v ↑s
⊢ Function.RightInverse
    (fun r =>
      { val := (interpolate s v) fun x => if hx : x ∈ s then r { val := x, property := hx } else 0,
        property :=
          (_ :
            ((interpolate s v) fun x => if hx : x ∈ s then r { val := x, property := hx } else 0) ∈
              degreeLT F (card s)) })
    {
          toAddHom :=
            { toFun := fun f i => eval (v ↑i) ↑f,
              map_add' :=
                (_ :
                  ∀ (f g : ↥(degreeLT F (card s))),
                    (fun f i => eval (v ↑i) ↑f) (f + g) =
                      (fun f i => eval (v ↑i) ↑f) f + (fun f i => eval (v ↑i) ↑f) g) },
          map_smul' :=
            (_ :
              ∀ (c : F) (f : ↥(degreeLT F (card s))),
                AddHom.toFun
                    { toFun := fun f i => eval (v ↑i) ↑f,
                      map_add' :=
                        (_ :
                          ∀ (f g : ↥(degreeLT F (card s))),
                            (fun f i => eval (v ↑i) ↑f) (f + g) =
                              (fun f i => eval (v ↑i) ↑f) f + (fun f i => eval (v ↑i) ↑f) g) }
                    (c • f) =
                  (RingHom.id F) c •
                    AddHom.toFun
                      { toFun := fun f i => eval (v ↑i) ↑f,
                        map_add' :=
                          (_ :
                            ∀ (f g : ↥(degreeLT F (card s))),
                              (fun f i => eval (v ↑i) ↑f) (f + g) =
                                (fun f i => eval (v ↑i) ↑f) f + (fun f i => eval (v ↑i) ↑f) g) }
                      f) }.toAddHom.toFun

Next tactic:
intro f
/-- Lagrange interpolation induces isomorphism between functions from `s`
and polynomials of degree less than `Fintype.card ι`.-/
def funEquivDegreeLT (hvs : Set.InjOn v s) : degreeLT F s.card ≃ₗ[F] s → F where
  toFun f i := f.1.eval (v i)
  map_add' f g := funext fun v => eval_add
  map_smul' c f := funext <| by simp
  invFun r :=
    ⟨interpolate s v fun x => if hx : x ∈ s then r ⟨x, hx⟩ else 0,
      mem_degreeLT.2 <| degree_interpolate_lt _ hvs⟩
  left_inv := by
    rintro ⟨f, hf⟩
    simp only [Subtype.mk_eq_mk, Subtype.coe_mk, dite_eq_ite]
    rw [mem_degreeLT] at hf
    conv => rhs; rw [eq_interpolate hvs hf]
    exact interpolate_eq_of_values_eq_on _ _ fun _ hi => if_pos hi
  right_inv := by
    intro f
    

Proof state:
F : Type u_1
inst✝¹ : Field F
ι : Type u_2
inst✝ : DecidableEq ι
s t : Finset ι
i j : ι
v r r' : ι → F
hvs : Set.InjOn v ↑s
f : { x // x ∈ s } → F
⊢ AddHom.toFun
      {
          toAddHom :=
            { toFun := fun f i => eval (v ↑i) ↑f,
              map_add' :=
                (_ :
                  ∀ (f g : ↥(degreeLT F (card s))),
                    (fun f i => eval (v ↑i) ↑f) (f + g) =
                      (fun f i => eval (v ↑i) ↑f) f + (fun f i => eval (v ↑i) ↑f) g) },
          map_smul' :=
            (_ :
              ∀ (c : F) (f : ↥(degreeLT F (card s))),
                AddHom.toFun
                    { toFun := fun f i => eval (v ↑i) ↑f,
                      map_add' :=
                        (_ :
                          ∀ (f g : ↥(degreeLT F (card s))),
                            (fun f i => eval (v ↑i) ↑f) (f + g) =
                              (fun f i => eval (v ↑i) ↑f) f + (fun f i => eval (v ↑i) ↑f) g) }
                    (c • f) =
                  (RingHom.id F) c •
                    AddHom.toFun
                      { toFun := fun f i => eval (v ↑i) ↑f,
                        map_add' :=
                          (_ :
                            ∀ (f g : ↥(degreeLT F (card s))),
                              (fun f i => eval (v ↑i) ↑f) (f + g) =
                                (fun f i => eval (v ↑i) ↑f) f + (fun f i => eval (v ↑i) ↑f) g) }
                      f) }.toAddHom
      ((fun r =>
          { val := (interpolate s v) fun x => if hx : x ∈ s then r { val := x, property := hx } else 0,
            property :=
              (_ :
                ((interpolate s v) fun x => if hx : x ∈ s then r { val := x, property := hx } else 0) ∈
                  degreeLT F (card s)) })
        f) =
    f

Next tactic:
ext ⟨i, hi⟩
/-- Lagrange interpolation induces isomorphism between functions from `s`
and polynomials of degree less than `Fintype.card ι`.-/
def funEquivDegreeLT (hvs : Set.InjOn v s) : degreeLT F s.card ≃ₗ[F] s → F where
  toFun f i := f.1.eval (v i)
  map_add' f g := funext fun v => eval_add
  map_smul' c f := funext <| by simp
  invFun r :=
    ⟨interpolate s v fun x => if hx : x ∈ s then r ⟨x, hx⟩ else 0,
      mem_degreeLT.2 <| degree_interpolate_lt _ hvs⟩
  left_inv := by
    rintro ⟨f, hf⟩
    simp only [Subtype.mk_eq_mk, Subtype.coe_mk, dite_eq_ite]
    rw [mem_degreeLT] at hf
    conv => rhs; rw [eq_interpolate hvs hf]
    exact interpolate_eq_of_values_eq_on _ _ fun _ hi => if_pos hi
  right_inv := by
    intro f
    ext ⟨i, hi⟩
    

Proof state:
case h.mk
F : Type u_1
inst✝¹ : Field F
ι : Type u_2
inst✝ : DecidableEq ι
s t : Finset ι
i✝ j : ι
v r r' : ι → F
hvs : Set.InjOn v ↑s
f : { x // x ∈ s } → F
i : ι
hi : i ∈ s
⊢ AddHom.toFun
      {
          toAddHom :=
            { toFun := fun f i => eval (v ↑i) ↑f,
              map_add' :=
                (_ :
                  ∀ (f g : ↥(degreeLT F (card s))),
                    (fun f i => eval (v ↑i) ↑f) (f + g) =
                      (fun f i => eval (v ↑i) ↑f) f + (fun f i => eval (v ↑i) ↑f) g) },
          map_smul' :=
            (_ :
              ∀ (c : F) (f : ↥(degreeLT F (card s))),
                AddHom.toFun
                    { toFun := fun f i => eval (v ↑i) ↑f,
                      map_add' :=
                        (_ :
                          ∀ (f g : ↥(degreeLT F (card s))),
                            (fun f i => eval (v ↑i) ↑f) (f + g) =
                              (fun f i => eval (v ↑i) ↑f) f + (fun f i => eval (v ↑i) ↑f) g) }
                    (c • f) =
                  (RingHom.id F) c •
                    AddHom.toFun
                      { toFun := fun f i => eval (v ↑i) ↑f,
                        map_add' :=
                          (_ :
                            ∀ (f g : ↥(degreeLT F (card s))),
                              (fun f i => eval (v ↑i) ↑f) (f + g) =
                                (fun f i => eval (v ↑i) ↑f) f + (fun f i => eval (v ↑i) ↑f) g) }
                      f) }.toAddHom
      ((fun r =>
          { val := (interpolate s v) fun x => if hx : x ∈ s then r { val := x, property := hx } else 0,
            property :=
              (_ :
                ((interpolate s v) fun x => if hx : x ∈ s then r { val := x, property := hx } else 0) ∈
                  degreeLT F (card s)) })
        f)
      { val := i, property := hi } =
    f { val := i, property := hi }

Next tactic:
simp only [Subtype.coe_mk, eval_interpolate_at_node _ hvs hi]