l3lab/ntp-mathlib huggingface dataset:
/-- Linear maps `(m → R) →ₗ[R] (n → R)` are linearly equivalent over `Rᵐᵒᵖ` to `Matrix m n R`,
by having matrices act by right multiplication.
 -/
def LinearMap.toMatrixRight' : ((m → R) →ₗ[R] n → R) ≃ₗ[Rᵐᵒᵖ] Matrix m n R where
  toFun f i j := f (stdBasis R (fun _ => R) i 1) j
  invFun := Matrix.vecMulLinear
  right_inv M := by
    ext i j
    simp only [Matrix.vecMul_stdBasis, Matrix.vecMulLinear_apply]
  left_inv f := by
    apply (Pi.basisFun R m).ext
    intro j; ext i
    

Proof state:
case h
R : Type u_1
inst✝² : Semiring R
l : Type u_2
m : Type u_3
n : Type u_4
inst✝¹ : Fintype m
inst✝ : DecidableEq m
f : (m → R) →ₗ[R] n → R
j : m
i : n
⊢ (vecMulLinear
        (AddHom.toFun
          {
              toAddHom :=
                { toFun := fun f i j => f ((stdBasis R (fun x => R) i) 1) j,
                  map_add' :=
                    (_ :
                      ∀ (f g : (m → R) →ₗ[R] n → R),
                        (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) (f + g) =
                          (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) f +
                            (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) g) },
              map_smul' :=
                (_ :
                  ∀ (c : Rᵐᵒᵖ) (f : (m → R) →ₗ[R] n → R),
                    AddHom.toFun
                        { toFun := fun f i j => f ((stdBasis R (fun x => R) i) 1) j,
                          map_add' :=
                            (_ :
                              ∀ (f g : (m → R) →ₗ[R] n → R),
                                (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) (f + g) =
                                  (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) f +
                                    (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) g) }
                        (c • f) =
                      (RingHom.id Rᵐᵒᵖ) c •
                        AddHom.toFun
                          { toFun := fun f i j => f ((stdBasis R (fun x => R) i) 1) j,
                            map_add' :=
                              (_ :
                                ∀ (f g : (m → R) →ₗ[R] n → R),
                                  (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) (f + g) =
                                    (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) f +
                                      (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) g) }
                          f) }.toAddHom
          f))
      ((Pi.basisFun R m) j) i =
    f ((Pi.basisFun R m) j) i

Next tactic:
simp only [Pi.basisFun_apply, Matrix.vecMul_stdBasis, Matrix.vecMulLinear_apply]
/-- Linear maps `(m → R) →ₗ[R] (n → R)` are linearly equivalent over `Rᵐᵒᵖ` to `Matrix m n R`,
by having matrices act by right multiplication.
 -/
def LinearMap.toMatrixRight' : ((m → R) →ₗ[R] n → R) ≃ₗ[Rᵐᵒᵖ] Matrix m n R where
  toFun f i j := f (stdBasis R (fun _ => R) i 1) j
  invFun := Matrix.vecMulLinear
  right_inv M := by
    

Proof state:
R : Type u_1
inst✝² : Semiring R
l : Type u_2
m : Type u_3
n : Type u_4
inst✝¹ : Fintype m
inst✝ : DecidableEq m
M : Matrix m n R
⊢ AddHom.toFun
      {
          toAddHom :=
            { toFun := fun f i j => f ((stdBasis R (fun x => R) i) 1) j,
              map_add' :=
                (_ :
                  ∀ (f g : (m → R) →ₗ[R] n → R),
                    (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) (f + g) =
                      (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) f +
                        (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) g) },
          map_smul' :=
            (_ :
              ∀ (c : Rᵐᵒᵖ) (f : (m → R) →ₗ[R] n → R),
                AddHom.toFun
                    { toFun := fun f i j => f ((stdBasis R (fun x => R) i) 1) j,
                      map_add' :=
                        (_ :
                          ∀ (f g : (m → R) →ₗ[R] n → R),
                            (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) (f + g) =
                              (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) f +
                                (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) g) }
                    (c • f) =
                  (RingHom.id Rᵐᵒᵖ) c •
                    AddHom.toFun
                      { toFun := fun f i j => f ((stdBasis R (fun x => R) i) 1) j,
                        map_add' :=
                          (_ :
                            ∀ (f g : (m → R) →ₗ[R] n → R),
                              (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) (f + g) =
                                (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) f +
                                  (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) g) }
                      f) }.toAddHom
      (vecMulLinear M) =
    M

Next tactic:
ext i j
/-- Linear maps `(m → R) →ₗ[R] (n → R)` are linearly equivalent over `Rᵐᵒᵖ` to `Matrix m n R`,
by having matrices act by right multiplication.
 -/
def LinearMap.toMatrixRight' : ((m → R) →ₗ[R] n → R) ≃ₗ[Rᵐᵒᵖ] Matrix m n R where
  toFun f i j := f (stdBasis R (fun _ => R) i 1) j
  invFun := Matrix.vecMulLinear
  right_inv M := by
    ext i j
    

Proof state:
case a.h
R : Type u_1
inst✝² : Semiring R
l : Type u_2
m : Type u_3
n : Type u_4
inst✝¹ : Fintype m
inst✝ : DecidableEq m
M : Matrix m n R
i : m
j : n
⊢ AddHom.toFun
      {
          toAddHom :=
            { toFun := fun f i j => f ((stdBasis R (fun x => R) i) 1) j,
              map_add' :=
                (_ :
                  ∀ (f g : (m → R) →ₗ[R] n → R),
                    (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) (f + g) =
                      (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) f +
                        (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) g) },
          map_smul' :=
            (_ :
              ∀ (c : Rᵐᵒᵖ) (f : (m → R) →ₗ[R] n → R),
                AddHom.toFun
                    { toFun := fun f i j => f ((stdBasis R (fun x => R) i) 1) j,
                      map_add' :=
                        (_ :
                          ∀ (f g : (m → R) →ₗ[R] n → R),
                            (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) (f + g) =
                              (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) f +
                                (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) g) }
                    (c • f) =
                  (RingHom.id Rᵐᵒᵖ) c •
                    AddHom.toFun
                      { toFun := fun f i j => f ((stdBasis R (fun x => R) i) 1) j,
                        map_add' :=
                          (_ :
                            ∀ (f g : (m → R) →ₗ[R] n → R),
                              (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) (f + g) =
                                (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) f +
                                  (fun f i j => f ((stdBasis R (fun x => R) i) 1) j) g) }
                      f) }.toAddHom
      (vecMulLinear M) i j =
    M i j

Next tactic:
simp only [Matrix.vecMul_stdBasis, Matrix.vecMulLinear_apply]
@[simp]
theorem Matrix.toLinearMapRight'_one :
    -- porting note: needs type annotation for `⇑` to resolve
    (Matrix.toLinearMapRight' : _ ≃ₗ[Rᵐᵒᵖ] _) (1 : Matrix m m R) = LinearMap.id := by
  

Proof state:
R : Type u_1
inst✝² : Semiring R
l : Type u_2
m : Type u_3
n : Type u_4
inst✝¹ : Fintype m
inst✝ : DecidableEq m
⊢ toLinearMapRight' 1 = LinearMap.id

Next tactic:
ext
@[simp]
theorem Matrix.toLinearMapRight'_one :
    -- porting note: needs type annotation for `⇑` to resolve
    (Matrix.toLinearMapRight' : _ ≃ₗ[Rᵐᵒᵖ] _) (1 : Matrix m m R) = LinearMap.id := by
  ext
  

Proof state:
case h.h.h
R : Type u_1
inst✝² : Semiring R
l : Type u_2
m : Type u_3
n : Type u_4
inst✝¹ : Fintype m
inst✝ : DecidableEq m
i✝ x✝ : m
⊢ (toLinearMapRight' 1 ∘ₗ single i✝) 1 x✝ = (LinearMap.id ∘ₗ single i✝) 1 x✝

Next tactic:
simp [LinearMap.one_apply, stdBasis_apply]
/-- If `M` and `M'` are each other's inverse matrices, they provide an equivalence between `n → A`
and `m → A` corresponding to `M.vecMul` and `M'.vecMul`. -/
@[simps]
def Matrix.toLinearEquivRight'OfInv [Fintype n] [DecidableEq n] {M : Matrix m n R}
    {M' : Matrix n m R} (hMM' : M * M' = 1) (hM'M : M' * M = 1) : (n → R) ≃ₗ[R] m → R :=
  { -- porting note: needs type annotation for `⇑` to resolve
    (LinearMap.toMatrixRight' : _ ≃ₗ[Rᵐᵒᵖ] _).symm
      M' with
    -- porting note: needs type annotation for `⇑` to resolve
    toFun := (Matrix.toLinearMapRight' : _ ≃ₗ[Rᵐᵒᵖ] _) M'
    -- porting note: needs type annotation for `⇑` to resolve
    invFun := (Matrix.toLinearMapRight' : _ ≃ₗ[Rᵐᵒᵖ] _) M
    left_inv := fun x => by
      

Proof state:
R : Type u_1
inst✝⁴ : Semiring R
l : Type u_2
m : Type u_3
n : Type u_4
inst✝³ : Fintype m
inst✝² : DecidableEq m
inst✝¹ : Fintype n
inst✝ : DecidableEq n
M : Matrix m n R
M' : Matrix n m R
hMM' : M * M' = 1
hM'M : M' * M = 1
src✝ : (n → R) →ₗ[R] m → R := (LinearEquiv.symm toMatrixRight') M'
x : n → R
⊢ (toLinearMapRight' M)
      (AddHom.toFun
        {
            toAddHom :=
              { toFun := ⇑(toLinearMapRight' M'),
                map_add' :=
                  (_ :
                    ∀ (x y : n → R),
                      AddHom.toFun src✝.toAddHom (x + y) =
                        AddHom.toFun src✝.toAddHom x + AddHom.toFun src✝.toAddHom y) },
            map_smul' :=
              (_ :
                ∀ (r : R) (x : n → R),
                  AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }.toAddHom
        x) =
    x

Next tactic:
dsimp only
/-- If `M` and `M'` are each other's inverse matrices, they provide an equivalence between `n → A`
and `m → A` corresponding to `M.vecMul` and `M'.vecMul`. -/
@[simps]
def Matrix.toLinearEquivRight'OfInv [Fintype n] [DecidableEq n] {M : Matrix m n R}
    {M' : Matrix n m R} (hMM' : M * M' = 1) (hM'M : M' * M = 1) : (n → R) ≃ₗ[R] m → R :=
  { -- porting note: needs type annotation for `⇑` to resolve
    (LinearMap.toMatrixRight' : _ ≃ₗ[Rᵐᵒᵖ] _).symm
      M' with
    -- porting note: needs type annotation for `⇑` to resolve
    toFun := (Matrix.toLinearMapRight' : _ ≃ₗ[Rᵐᵒᵖ] _) M'
    -- porting note: needs type annotation for `⇑` to resolve
    invFun := (Matrix.toLinearMapRight' : _ ≃ₗ[Rᵐᵒᵖ] _) M
    left_inv := fun x => by
      dsimp only -- porting note: needed due to non-flat structures
      

Proof state:
R : Type u_1
inst✝⁴ : Semiring R
l : Type u_2
m : Type u_3
n : Type u_4
inst✝³ : Fintype m
inst✝² : DecidableEq m
inst✝¹ : Fintype n
inst✝ : DecidableEq n
M : Matrix m n R
M' : Matrix n m R
hMM' : M * M' = 1
hM'M : M' * M = 1
src✝ : (n → R) →ₗ[R] m → R := (LinearEquiv.symm toMatrixRight') M'
x : n → R
⊢ (toLinearMapRight' M) ((toLinearMapRight' M') x) = x

Next tactic:
rw [← Matrix.toLinearMapRight'_mul_apply, hM'M, Matrix.toLinearMapRight'_one, id_apply]
/-- If `M` and `M'` are each other's inverse matrices, they provide an equivalence between `n → A`
and `m → A` corresponding to `M.vecMul` and `M'.vecMul`. -/
@[simps]
def Matrix.toLinearEquivRight'OfInv [Fintype n] [DecidableEq n] {M : Matrix m n R}
    {M' : Matrix n m R} (hMM' : M * M' = 1) (hM'M : M' * M = 1) : (n → R) ≃ₗ[R] m → R :=
  { -- porting note: needs type annotation for `⇑` to resolve
    (LinearMap.toMatrixRight' : _ ≃ₗ[Rᵐᵒᵖ] _).symm
      M' with
    -- porting note: needs type annotation for `⇑` to resolve
    toFun := (Matrix.toLinearMapRight' : _ ≃ₗ[Rᵐᵒᵖ] _) M'
    -- porting note: needs type annotation for `⇑` to resolve
    invFun := (Matrix.toLinearMapRight' : _ ≃ₗ[Rᵐᵒᵖ] _) M
    left_inv := fun x => by
      dsimp only -- porting note: needed due to non-flat structures
      rw [← Matrix.toLinearMapRight'_mul_apply, hM'M, Matrix.toLinearMapRight'_one, id_apply]
    right_inv := fun x => by
      

Proof state:
R : Type u_1
inst✝⁴ : Semiring R
l : Type u_2
m : Type u_3
n : Type u_4
inst✝³ : Fintype m
inst✝² : DecidableEq m
inst✝¹ : Fintype n
inst✝ : DecidableEq n
M : Matrix m n R
M' : Matrix n m R
hMM' : M * M' = 1
hM'M : M' * M = 1
src✝ : (n → R) →ₗ[R] m → R := (LinearEquiv.symm toMatrixRight') M'
x : m → R
⊢ AddHom.toFun
      {
          toAddHom :=
            { toFun := ⇑(toLinearMapRight' M'),
              map_add' :=
                (_ :
                  ∀ (x y : n → R),
                    AddHom.toFun src✝.toAddHom (x + y) = AddHom.toFun src✝.toAddHom x + AddHom.toFun src✝.toAddHom y) },
          map_smul' :=
            (_ :
              ∀ (r : R) (x : n → R),
                AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }.toAddHom
      ((toLinearMapRight' M) x) =
    x

Next tactic:
dsimp only
/-- If `M` and `M'` are each other's inverse matrices, they provide an equivalence between `n → A`
and `m → A` corresponding to `M.vecMul` and `M'.vecMul`. -/
@[simps]
def Matrix.toLinearEquivRight'OfInv [Fintype n] [DecidableEq n] {M : Matrix m n R}
    {M' : Matrix n m R} (hMM' : M * M' = 1) (hM'M : M' * M = 1) : (n → R) ≃ₗ[R] m → R :=
  { -- porting note: needs type annotation for `⇑` to resolve
    (LinearMap.toMatrixRight' : _ ≃ₗ[Rᵐᵒᵖ] _).symm
      M' with
    -- porting note: needs type annotation for `⇑` to resolve
    toFun := (Matrix.toLinearMapRight' : _ ≃ₗ[Rᵐᵒᵖ] _) M'
    -- porting note: needs type annotation for `⇑` to resolve
    invFun := (Matrix.toLinearMapRight' : _ ≃ₗ[Rᵐᵒᵖ] _) M
    left_inv := fun x => by
      dsimp only -- porting note: needed due to non-flat structures
      rw [← Matrix.toLinearMapRight'_mul_apply, hM'M, Matrix.toLinearMapRight'_one, id_apply]
    right_inv := fun x => by
      dsimp only -- porting note: needed due to non-flat structures
      

Proof state:
R : Type u_1
inst✝⁴ : Semiring R
l : Type u_2
m : Type u_3
n : Type u_4
inst✝³ : Fintype m
inst✝² : DecidableEq m
inst✝¹ : Fintype n
inst✝ : DecidableEq n
M : Matrix m n R
M' : Matrix n m R
hMM' : M * M' = 1
hM'M : M' * M = 1
src✝ : (n → R) →ₗ[R] m → R := (LinearEquiv.symm toMatrixRight') M'
x : m → R
⊢ (toLinearMapRight' M') ((toLinearMapRight' M) x) = x

Next tactic:
rw [← Matrix.toLinearMapRight'_mul_apply, hMM', Matrix.toLinearMapRight'_one, id_apply]
@[simp] theorem Matrix.mulVecLin_transpose [Fintype m] (M : Matrix m n R) :
    Mᵀ.mulVecLin = M.vecMulLinear := by
  

Proof state:
R : Type u_1
inst✝¹ : CommSemiring R
k : Type u_2
l : Type u_3
m : Type u_4
n : Type u_5
inst✝ : Fintype m
M : Matrix m n R
⊢ mulVecLin Mᵀ = vecMulLinear M

Next tactic:
ext
@[simp] theorem Matrix.mulVecLin_transpose [Fintype m] (M : Matrix m n R) :
    Mᵀ.mulVecLin = M.vecMulLinear := by
  ext; 

Proof state:
case h.h
R : Type u_1
inst✝¹ : CommSemiring R
k : Type u_2
l : Type u_3
m : Type u_4
n : Type u_5
inst✝ : Fintype m
M : Matrix m n R
x✝¹ : m → R
x✝ : n
⊢ (mulVecLin Mᵀ) x✝¹ x✝ = (vecMulLinear M) x✝¹ x✝

Next tactic:
simp [mulVec_transpose]
@[simp] theorem Matrix.vecMulLinear_transpose [Fintype n] (M : Matrix m n R) :
    Mᵀ.vecMulLinear = M.mulVecLin := by
  

Proof state:
R : Type u_1
inst✝¹ : CommSemiring R
k : Type u_2
l : Type u_3
m : Type u_4
n : Type u_5
inst✝ : Fintype n
M : Matrix m n R
⊢ vecMulLinear Mᵀ = mulVecLin M

Next tactic:
ext
@[simp] theorem Matrix.vecMulLinear_transpose [Fintype n] (M : Matrix m n R) :
    Mᵀ.vecMulLinear = M.mulVecLin := by
  ext; 

Proof state:
case h.h
R : Type u_1
inst✝¹ : CommSemiring R
k : Type u_2
l : Type u_3
m : Type u_4
n : Type u_5
inst✝ : Fintype n
M : Matrix m n R
x✝¹ : n → R
x✝ : m
⊢ (vecMulLinear Mᵀ) x✝¹ x✝ = (mulVecLin M) x✝¹ x✝

Next tactic:
simp [vecMul_transpose]
@[simp]
theorem Matrix.mulVecLin_one [DecidableEq n] :
    Matrix.mulVecLin (1 : Matrix n n R) = LinearMap.id := by
  

Proof state:
R : Type u_1
inst✝² : CommSemiring R
k : Type u_2
l : Type u_3
m : Type u_4
n : Type u_5
inst✝¹ : Fintype n
inst✝ : DecidableEq n
⊢ mulVecLin 1 = LinearMap.id

Next tactic:
ext
@[simp]
theorem Matrix.mulVecLin_one [DecidableEq n] :
    Matrix.mulVecLin (1 : Matrix n n R) = LinearMap.id := by
  ext; 

Proof state:
case h.h.h
R : Type u_1
inst✝² : CommSemiring R
k : Type u_2
l : Type u_3
m : Type u_4
n : Type u_5
inst✝¹ : Fintype n
inst✝ : DecidableEq n
i✝ x✝ : n
⊢ (mulVecLin 1 ∘ₗ single i✝) 1 x✝ = (LinearMap.id ∘ₗ single i✝) 1 x✝

Next tactic:
simp [Matrix.one_apply, Pi.single_apply]
theorem Matrix.ker_mulVecLin_eq_bot_iff {M : Matrix m n R} :
    (LinearMap.ker M.mulVecLin) = ⊥ ↔ ∀ v, M.mulVec v = 0 → v = 0 := by
  

Proof state:
R : Type u_1
inst✝¹ : CommSemiring R
k : Type u_2
l : Type u_3
m : Type u_4
n : Type u_5
inst✝ : Fintype n
M : Matrix m n R
⊢ ker (mulVecLin M) = ⊥ ↔ ∀ (v : n → R), mulVec M v = 0 → v = 0

Next tactic:
simp only [Submodule.eq_bot_iff, LinearMap.mem_ker, Matrix.mulVecLin_apply]
theorem Matrix.range_mulVecLin (M : Matrix m n R) :
    LinearMap.range M.mulVecLin = span R (range Mᵀ) := by
  

Proof state:
R : Type u_1
inst✝¹ : CommSemiring R
k : Type u_2
l : Type u_3
m : Type u_4
n : Type u_5
inst✝ : Fintype n
M : Matrix m n R
⊢ LinearMap.range (mulVecLin M) = span R (Set.range Mᵀ)

Next tactic:
rw [← vecMulLinear_transpose, range_vecMulLinear]
theorem Matrix.mulVec_injective_iff {R : Type*} [CommRing R] {M : Matrix m n R} :
    Function.Injective M.mulVec ↔ LinearIndependent R (fun i ↦ Mᵀ i) := by
  

Proof state:
R✝ : Type u_1
inst✝² : CommSemiring R✝
k : Type u_2
l : Type u_3
m : Type u_4
n : Type u_5
inst✝¹ : Fintype n
R : Type u_6
inst✝ : CommRing R
M : Matrix m n R
⊢ Function.Injective (mulVec M) ↔ LinearIndependent R fun i => Mᵀ i

Next tactic:
change Function.Injective (fun x ↦ _) ↔ _
theorem Matrix.mulVec_injective_iff {R : Type*} [CommRing R] {M : Matrix m n R} :
    Function.Injective M.mulVec ↔ LinearIndependent R (fun i ↦ Mᵀ i) := by
  change Function.Injective (fun x ↦ _) ↔ _
  

Proof state:
R✝ : Type u_1
inst✝² : CommSemiring R✝
k : Type u_2
l : Type u_3
m : Type u_4
n : Type u_5
inst✝¹ : Fintype n
R : Type u_6
inst✝ : CommRing R
M : Matrix m n R
⊢ (Function.Injective fun x => mulVec M x) ↔ LinearIndependent R fun i => Mᵀ i

Next tactic:
simp_rw [← M.vecMul_transpose, vecMul_injective_iff]
/-- Linear maps `(n → R) →ₗ[R] (m → R)` are linearly equivalent to `Matrix m n R`. -/
def LinearMap.toMatrix' : ((n → R) →ₗ[R] m → R) ≃ₗ[R] Matrix m n R where
  toFun f := of fun i j => f (stdBasis R (fun _ => R) j 1) i
  invFun := Matrix.mulVecLin
  right_inv M := by
    ext i j
    simp only [Matrix.mulVec_stdBasis, Matrix.mulVecLin_apply, of_apply]
  left_inv f := by
    apply (Pi.basisFun R n).ext
    intro j; ext i
    simp only [Pi.basisFun_apply, Matrix.mulVec_stdBasis, Matrix.mulVecLin_apply, of_apply]
  map_add' f g := by
    

Proof state:
R : Type u_1
inst✝² : CommSemiring R
k : Type u_2
l : Type u_3
m : Type u_4
n : Type u_5
inst✝¹ : DecidableEq n
inst✝ : Fintype n
f g : (n → R) →ₗ[R] m → R
⊢ (fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i) (f + g) =
    (fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i) f +
      (fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i) g

Next tactic:
ext i j
/-- Linear maps `(n → R) →ₗ[R] (m → R)` are linearly equivalent to `Matrix m n R`. -/
def LinearMap.toMatrix' : ((n → R) →ₗ[R] m → R) ≃ₗ[R] Matrix m n R where
  toFun f := of fun i j => f (stdBasis R (fun _ => R) j 1) i
  invFun := Matrix.mulVecLin
  right_inv M := by
    ext i j
    simp only [Matrix.mulVec_stdBasis, Matrix.mulVecLin_apply, of_apply]
  left_inv f := by
    apply (Pi.basisFun R n).ext
    intro j; ext i
    simp only [Pi.basisFun_apply, Matrix.mulVec_stdBasis, Matrix.mulVecLin_apply, of_apply]
  map_add' f g := by
    ext i j
    

Proof state:
case a.h
R : Type u_1
inst✝² : CommSemiring R
k : Type u_2
l : Type u_3
m : Type u_4
n : Type u_5
inst✝¹ : DecidableEq n
inst✝ : Fintype n
f g : (n → R) →ₗ[R] m → R
i : m
j : n
⊢ (fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i) (f + g) i j =
    ((fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i) f +
        (fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i) g)
      i j

Next tactic:
simp only [Pi.add_apply, LinearMap.add_apply, of_apply, Matrix.add_apply]
/-- Linear maps `(n → R) →ₗ[R] (m → R)` are linearly equivalent to `Matrix m n R`. -/
def LinearMap.toMatrix' : ((n → R) →ₗ[R] m → R) ≃ₗ[R] Matrix m n R where
  toFun f := of fun i j => f (stdBasis R (fun _ => R) j 1) i
  invFun := Matrix.mulVecLin
  right_inv M := by
    ext i j
    simp only [Matrix.mulVec_stdBasis, Matrix.mulVecLin_apply, of_apply]
  left_inv f := by
    apply (Pi.basisFun R n).ext
    intro j; ext i
    simp only [Pi.basisFun_apply, Matrix.mulVec_stdBasis, Matrix.mulVecLin_apply, of_apply]
  map_add' f g := by
    ext i j
    simp only [Pi.add_apply, LinearMap.add_apply, of_apply, Matrix.add_apply]
  map_smul' c f := by
    

Proof state:
R : Type u_1
inst✝² : CommSemiring R
k : Type u_2
l : Type u_3
m : Type u_4
n : Type u_5
inst✝¹ : DecidableEq n
inst✝ : Fintype n
c : R
f : (n → R) →ₗ[R] m → R
⊢ AddHom.toFun
      { toFun := fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i,
        map_add' :=
          (_ :
            ∀ (f g : (n → R) →ₗ[R] m → R),
              (fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i) (f + g) =
                (fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i) f +
                  (fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i) g) }
      (c • f) =
    (RingHom.id R) c •
      AddHom.toFun
        { toFun := fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i,
          map_add' :=
            (_ :
              ∀ (f g : (n → R) →ₗ[R] m → R),
                (fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i) (f + g) =
                  (fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i) f +
                    (fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i) g) }
        f

Next tactic:
ext i j
/-- Linear maps `(n → R) →ₗ[R] (m → R)` are linearly equivalent to `Matrix m n R`. -/
def LinearMap.toMatrix' : ((n → R) →ₗ[R] m → R) ≃ₗ[R] Matrix m n R where
  toFun f := of fun i j => f (stdBasis R (fun _ => R) j 1) i
  invFun := Matrix.mulVecLin
  right_inv M := by
    ext i j
    simp only [Matrix.mulVec_stdBasis, Matrix.mulVecLin_apply, of_apply]
  left_inv f := by
    apply (Pi.basisFun R n).ext
    intro j; ext i
    simp only [Pi.basisFun_apply, Matrix.mulVec_stdBasis, Matrix.mulVecLin_apply, of_apply]
  map_add' f g := by
    ext i j
    simp only [Pi.add_apply, LinearMap.add_apply, of_apply, Matrix.add_apply]
  map_smul' c f := by
    ext i j
    

Proof state:
case a.h
R : Type u_1
inst✝² : CommSemiring R
k : Type u_2
l : Type u_3
m : Type u_4
n : Type u_5
inst✝¹ : DecidableEq n
inst✝ : Fintype n
c : R
f : (n → R) →ₗ[R] m → R
i : m
j : n
⊢ AddHom.toFun
      { toFun := fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i,
        map_add' :=
          (_ :
            ∀ (f g : (n → R) →ₗ[R] m → R),
              (fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i) (f + g) =
                (fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i) f +
                  (fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i) g) }
      (c • f) i j =
    ((RingHom.id R) c •
        AddHom.toFun
          { toFun := fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i,
            map_add' :=
              (_ :
                ∀ (f g : (n → R) →ₗ[R] m → R),
                  (fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i) (f + g) =
                    (fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i) f +
                      (fun f => of fun i j => f ((stdBasis R (fun x => R) j) 1) i) g) }
          f)
      i j

Next tactic:
simp only [Pi.smul_apply, LinearMap.smul_apply, RingHom.id_apply, of_apply, Matrix.smul_apply]