@@ -274,3 +274,80 @@ theorem homTensorHomEquiv_apply (x : (M →ₗ[R] P) ⊗[R] (N →ₗ[R] Q)) :
274274end CommSemiring
275275
276276end HomTensorHom
277+
278+ namespace TensorProduct
279+
280+ open LinearMap Module
281+
282+ variable {R M N : Type *} {ι κ : Type *}
283+ variable [DecidableEq ι] [DecidableEq κ]
284+ variable [Fintype ι] [Fintype κ]
285+
286+ attribute [local ext] TensorProduct.ext
287+
288+ variable [CommSemiring R] [AddCommMonoid M] [AddCommMonoid N]
289+ variable [Module R M] [Module R N]
290+
291+ /-- An inverse to `TensorProduct.dualDistrib` given bases.
292+ -/
293+ noncomputable def dualDistribInvOfBasis (b : Basis ι R M) (c : Basis κ R N) :
294+ Dual R (M ⊗[R] N) →ₗ[R] Dual R M ⊗[R] Dual R N :=
295+ ∑ i, ∑ j,
296+ (ringLmapEquivSelf R ℕ _).symm (b.dualBasis i ⊗ₜ c.dualBasis j) ∘ₗ
297+ applyₗ (c j) ∘ₗ applyₗ (b i) ∘ₗ lcurry (.id R) M N R
298+
299+ @[simp]
300+ theorem dualDistribInvOfBasis_apply (b : Basis ι R M) (c : Basis κ R N) (f : Dual R (M ⊗[R] N)) :
301+ dualDistribInvOfBasis b c f = ∑ i, ∑ j, f (b i ⊗ₜ c j) • b.dualBasis i ⊗ₜ c.dualBasis j := by
302+ simp [dualDistribInvOfBasis]
303+
304+ theorem dualDistrib_dualDistribInvOfBasis_left_inverse (b : Basis ι R M) (c : Basis κ R N) :
305+ comp (dualDistrib R M N) (dualDistribInvOfBasis b c) = LinearMap.id := by
306+ apply (b.tensorProduct c).dualBasis.ext
307+ rintro ⟨i, j⟩
308+ apply (b.tensorProduct c).ext
309+ rintro ⟨i', j'⟩
310+ simp only [dualDistrib, Basis.coe_dualBasis, coe_comp, Function.comp_apply,
311+ dualDistribInvOfBasis_apply, Basis.coord_apply, Basis.tensorProduct_repr_tmul_apply,
312+ Basis.repr_self, _root_.map_sum, map_smul, homTensorHomMap_apply, compRight_apply,
313+ Basis.tensorProduct_apply, LinearMap.coe_sum, Finset.sum_apply, smul_apply, LinearEquiv.coe_coe,
314+ map_tmul, lid_tmul, smul_eq_mul, id_coe, id_eq]
315+ rw [Finset.sum_eq_single i, Finset.sum_eq_single j]
316+ · simpa using mul_comm _ _
317+ all_goals { intros; simp [*] at * }
318+
319+ theorem dualDistrib_dualDistribInvOfBasis_right_inverse (b : Basis ι R M) (c : Basis κ R N) :
320+ comp (dualDistribInvOfBasis b c) (dualDistrib R M N) = LinearMap.id := by
321+ apply (b.dualBasis.tensorProduct c.dualBasis).ext
322+ rintro ⟨i, j⟩
323+ simp only [Basis.tensorProduct_apply, Basis.coe_dualBasis, coe_comp, Function.comp_apply,
324+ dualDistribInvOfBasis_apply, dualDistrib_apply, Basis.coord_apply, Basis.repr_self,
325+ id_coe, id_eq]
326+ rw [Finset.sum_eq_single i, Finset.sum_eq_single j]
327+ · simp
328+ all_goals { intros; simp [*] at * }
329+
330+ /-- A linear equivalence between `Dual M ⊗ Dual N` and `Dual (M ⊗ N)` given bases for `M` and `N`.
331+ It sends `f ⊗ g` to the composition of `TensorProduct.map f g` with the natural
332+ isomorphism `R ⊗ R ≃ R`.
333+ -/
334+ @[simps!]
335+ noncomputable def dualDistribEquivOfBasis (b : Basis ι R M) (c : Basis κ R N) :
336+ Dual R M ⊗[R] Dual R N ≃ₗ[R] Dual R (M ⊗[R] N) := by
337+ refine LinearEquiv.ofLinear (dualDistrib R M N) (dualDistribInvOfBasis b c) ?_ ?_
338+ · exact dualDistrib_dualDistribInvOfBasis_left_inverse _ _
339+ · exact dualDistrib_dualDistribInvOfBasis_right_inverse _ _
340+
341+ variable (R M N)
342+ variable [Module.Finite R M] [Module.Finite R N] [Module.Free R M] [Module.Free R N]
343+
344+ /--
345+ A linear equivalence between `Dual M ⊗ Dual N` and `Dual (M ⊗ N)` when `M` and `N` are finite free
346+ modules. It sends `f ⊗ g` to the composition of `TensorProduct.map f g` with the natural
347+ isomorphism `R ⊗ R ≃ R`.
348+ -/
349+ @[simp]
350+ noncomputable def dualDistribEquiv : Dual R M ⊗[R] Dual R N ≃ₗ[R] Dual R (M ⊗[R] N) :=
351+ dualDistribEquivOfBasis (Module.Free.chooseBasis R M) (Module.Free.chooseBasis R N)
352+
353+ end TensorProduct
0 commit comments