Skip to content

Commit 472450d

Browse files
committed
feat: heterogenize TensorProduct.congr and friends (#6035)
The summary is that this PR: * generalizes a handful of results to non-commutative algebras (simply by moving them to an earlier section) * adds heterogenous versions of `map`, `congr`, `mapBilinear`, `homTensorHom`, `leftComm`, `tensorTensorTensorComm` * generalizes `lcurry`, `uncurry`, and `assoc` to take an extra algebra, such that the `A`s in the two different places can separately be replaced with `R` The punchline here is really: ```lean def tensorTensorTensorComm : (M ⊗[R] N) ⊗[A] (P ⊗[R] Q) ≃ₗ[A] (M ⊗[A] P) ⊗[R] (N ⊗[R] Q) := ``` which is valuable for a base change / tensor product of bilinear forms when instantiated as ```lean (M ⊗[R] N) ⊗[A] (Dual A M ⊗[R] Dual R N) ≃ₗ[A] (M ⊗[A] Dual A M) ⊗[R] (N ⊗[R] Dual R N) ``` It would not surprise me if it's possible to introduce a third ring into `tensorTensorTensorComm`, but for now I'd prefer to assume that for that particular definition, two rings is enough for anybody! Unfortunately, this was not the case for `lcurry`, `uncurry`, and `assoc`, which really do need to work over three rings so that the `A`s in the two different places can separately be replaced with `R`; both permutations are needed in the construction of `tensorTensorTensorComm`, and it seemed preferable to not have a plethora of primed variants. I make no claim that the pile of `IsScalarTower` and `SMulCommClass` arguments here are in any sense optimal, besides the fact they specifically enable the use-case I have for the base change of bilinear forms.
1 parent 44692e2 commit 472450d

2 files changed

Lines changed: 233 additions & 52 deletions

File tree

Mathlib/LinearAlgebra/TensorProduct/Tower.lean

Lines changed: 231 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/-
22
Copyright (c) 2020 Scott Morrison. All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
4-
Authors: Scott Morrison, Johan Commelin
4+
Authors: Scott Morrison, Johan Commelin, Eric Wieser
55
-/
66
import Mathlib.LinearAlgebra.TensorProduct
77
import Mathlib.Algebra.Algebra.Tower
@@ -14,8 +14,11 @@ import Mathlib.Algebra.Algebra.Tower
1414
When `M` is both an `R`-module and an `A`-module, and `Algebra R A`, then many of the morphisms
1515
preserve the actions by `A`.
1616
17-
This file provides more general versions of the definitions already in
18-
`LinearAlgebra/TensorProduct`.
17+
The `Module` instance itself is provided elsewhere as `TensorProduct.leftModule`. This file provides
18+
more general versions of the definitions already in `LinearAlgebra/TensorProduct`.
19+
20+
In this file, we use the convention that `M`, `N`, `P`, `Q` are all `R`-modules, but only `M` and
21+
`P` are simultaneously `A`-modules.
1922
2023
## Main definitions
2124
@@ -25,7 +28,14 @@ This file provides more general versions of the definitions already in
2528
* `TensorProduct.AlgebraTensorModule.lift`
2629
* `TensorProduct.AlgebraTensorModule.lift.equiv`
2730
* `TensorProduct.AlgebraTensorModule.mk`
31+
* `TensorProduct.AlgebraTensorModule.map`
32+
* `TensorProduct.AlgebraTensorModule.mapBilinear`
33+
* `TensorProduct.AlgebraTensorModule.congr`
34+
* `TensorProduct.AlgebraTensorModule.homTensorHomMap`
2835
* `TensorProduct.AlgebraTensorModule.assoc`
36+
* `TensorProduct.AlgebraTensorModule.leftComm`
37+
* `TensorProduct.AlgebraTensorModule.rightComm`
38+
* `TensorProduct.AlgebraTensorModule.tensorTensorTensorComm`
2939
3040
## Implementation notes
3141
@@ -38,20 +48,26 @@ namespace TensorProduct
3848

3949
namespace AlgebraTensorModule
4050

41-
variable {R A M N P : Type _}
51+
universe uR uA uB uM uN uP uQ
52+
variable {R : Type uR} {A : Type uA} {B : Type uB}
53+
variable {M : Type uM} {N : Type uN} {P : Type uP} {Q : Type uQ}
4254

4355
open LinearMap
4456
open Algebra (lsmul)
4557

4658
section Semiring
4759

48-
variable [CommSemiring R] [Semiring A] [Algebra R A]
60+
variable [CommSemiring R] [Semiring A] [Semiring B] [Algebra R A] [Algebra R B]
4961

50-
variable [AddCommMonoid M] [Module R M] [Module A M] [IsScalarTower R A M]
62+
variable [AddCommMonoid M] [Module R M] [Module A M] [Module B M]
63+
variable [IsScalarTower R A M] [IsScalarTower R B M] [SMulCommClass A B M]
5164

5265
variable [AddCommMonoid N] [Module R N]
5366

54-
variable [AddCommMonoid P] [Module R P] [Module A P] [IsScalarTower R A P]
67+
variable [AddCommMonoid P] [Module R P] [Module A P] [Module B P]
68+
variable [IsScalarTower R A P] [IsScalarTower R B P] [SMulCommClass A B P]
69+
70+
variable [AddCommMonoid Q] [Module R Q]
5571

5672
theorem smul_eq_lsmul_rTensor (a : A) (x : M ⊗[R] N) : a • x = (lsmul R R M a).rTensor N x :=
5773
rfl
@@ -89,18 +105,6 @@ theorem ext {g h : M ⊗[R] N →ₗ[A] P} (H : ∀ x y, g (x ⊗ₜ y) = h (x
89105
curry_injective <| LinearMap.ext₂ H
90106
#align tensor_product.algebra_tensor_module.ext TensorProduct.AlgebraTensorModule.ext
91107

92-
end Semiring
93-
94-
section CommSemiring
95-
96-
variable [CommSemiring R] [CommSemiring A] [Algebra R A]
97-
98-
variable [AddCommMonoid M] [Module R M] [Module A M] [IsScalarTower R A M]
99-
100-
variable [AddCommMonoid N] [Module R N]
101-
102-
variable [AddCommMonoid P] [Module R P] [Module A P] [IsScalarTower R A P]
103-
104108
/-- Heterobasic version of `TensorProduct.lift`:
105109
106110
Constructing a linear map `M ⊗[R] N →[A] P` given a bilinear map `M →[A] N →[R] P` with the
@@ -131,41 +135,44 @@ theorem lift_tmul (f : M →ₗ[A] N →ₗ[R] P) (x : M) (y : N) : lift f (x
131135
rfl
132136
#align tensor_product.algebra_tensor_module.lift_tmul TensorProduct.AlgebraTensorModule.lift_tmul
133137

134-
variable (R A M N P)
138+
variable (R A B M N P Q)
135139

136140
/-- Heterobasic version of `TensorProduct.uncurry`:
137141
138142
Linearly constructing a linear map `M ⊗[R] N →[A] P` given a bilinear map `M →[A] N →[R] P`
139143
with the property that its composition with the canonical bilinear map `M →[A] N →[R] M ⊗[R] N` is
140144
the given bilinear map `M →[A] N →[R] P`. -/
141145
@[simps]
142-
def uncurry : (M →ₗ[A] N →ₗ[R] P) →ₗ[A] M ⊗[R] N →ₗ[A] P where
146+
def uncurry : (M →ₗ[A] N →ₗ[R] P) →ₗ[B] M ⊗[R] N →ₗ[A] P where
143147
toFun := lift
144148
map_add' _ _ := ext fun x y => by simp only [lift_tmul, add_apply]
145149
map_smul' _ _ := ext fun x y => by simp only [lift_tmul, smul_apply, RingHom.id_apply]
146-
#align tensor_product.algebra_tensor_module.uncurry TensorProduct.AlgebraTensorModule.uncurry
150+
-- porting note: new `B` argument
151+
#align tensor_product.algebra_tensor_module.uncurry TensorProduct.AlgebraTensorModule.uncurryₓ
147152

148153
/-- Heterobasic version of `TensorProduct.lcurry`:
149154
150155
Given a linear map `M ⊗[R] N →[A] P`, compose it with the canonical
151156
bilinear map `M →[A] N →[R] M ⊗[R] N` to form a bilinear map `M →[A] N →[R] P`. -/
152157
@[simps]
153-
def lcurry : (M ⊗[R] N →ₗ[A] P) →ₗ[A] M →ₗ[A] N →ₗ[R] P where
158+
def lcurry : (M ⊗[R] N →ₗ[A] P) →ₗ[B] M →ₗ[A] N →ₗ[R] P where
154159
toFun := curry
155160
map_add' _ _ := rfl
156161
map_smul' _ _ := rfl
157-
#align tensor_product.algebra_tensor_module.lcurry TensorProduct.AlgebraTensorModule.lcurry
162+
-- porting note: new `B` argument
163+
#align tensor_product.algebra_tensor_module.lcurry TensorProduct.AlgebraTensorModule.lcurryₓ
158164

159165
/-- Heterobasic version of `TensorProduct.lift.equiv`:
160166
161167
A linear equivalence constructing a linear map `M ⊗[R] N →[A] P` given a
162168
bilinear map `M →[A] N →[R] P` with the property that its composition with the
163169
canonical bilinear map `M →[A] N →[R] M ⊗[R] N` is the given bilinear map `M →[A] N →[R] P`. -/
164-
def lift.equiv : (M →ₗ[A] N →ₗ[R] P) ≃ₗ[A] M ⊗[R] N →ₗ[A] P :=
165-
LinearEquiv.ofLinear (uncurry R A M N P) (lcurry R A M N P)
170+
def lift.equiv : (M →ₗ[A] N →ₗ[R] P) ≃ₗ[B] M ⊗[R] N →ₗ[A] P :=
171+
LinearEquiv.ofLinear (uncurry R A B M N P) (lcurry R A B M N P)
166172
(LinearMap.ext fun _ => ext fun x y => lift_tmul _ x y)
167173
(LinearMap.ext fun f => LinearMap.ext fun x => LinearMap.ext fun y => lift_tmul f x y)
168-
#align tensor_product.algebra_tensor_module.lift.equiv TensorProduct.AlgebraTensorModule.lift.equiv
174+
-- porting note: new `B` argument
175+
#align tensor_product.algebra_tensor_module.lift.equiv TensorProduct.AlgebraTensorModule.lift.equivₓ
169176

170177
/-- Heterobasic version of `TensorProduct.mk`:
171178
@@ -176,27 +183,208 @@ nonrec def mk : M →ₗ[A] N →ₗ[R] M ⊗[R] N :=
176183
#align tensor_product.algebra_tensor_module.mk TensorProduct.AlgebraTensorModule.mk
177184
#align tensor_product.algebra_tensor_module.mk_apply TensorProduct.AlgebraTensorModule.mk_apply
178185

186+
variable {R A B M N P Q}
187+
188+
/-- Heterobasic version of `TensorProduct.map` -/
189+
def map (f : M →ₗ[A] P) (g : N →ₗ[R] Q) : M ⊗[R] N →ₗ[A] P ⊗[R] Q :=
190+
lift <|
191+
{ toFun := fun h => h ∘ₗ g,
192+
map_add' := fun h₁ h₂ => LinearMap.add_comp g h₂ h₁,
193+
map_smul' := fun c h => LinearMap.smul_comp c h g } ∘ₗ mk R A P Q ∘ₗ f
194+
195+
@[simp] theorem map_tmul (f : M →ₗ[A] P) (g : N →ₗ[R] Q) (m : M) (n : N) :
196+
map f g (m ⊗ₜ n) = f m ⊗ₜ g n :=
197+
rfl
198+
199+
theorem map_add_left (f₁ f₂ : M →ₗ[A] P) (g : N →ₗ[R] Q) :
200+
map (f₁ + f₂) g = map f₁ g + map f₂ g := by
201+
ext
202+
simp_rw [curry_apply, TensorProduct.curry_apply, restrictScalars_apply, add_apply, map_tmul,
203+
add_apply, add_tmul]
204+
205+
theorem map_add_right (f : M →ₗ[A] P) (g₁ g₂ : N →ₗ[R] Q) :
206+
map f (g₁ + g₂) = map f g₁ + map f g₂ := by
207+
ext
208+
simp_rw [curry_apply, TensorProduct.curry_apply, restrictScalars_apply, add_apply, map_tmul,
209+
add_apply, tmul_add]
210+
211+
theorem map_smul_right (r : R) (f : M →ₗ[A] P) (g : N →ₗ[R] Q) : map f (r • g) = r • map f g := by
212+
ext
213+
simp_rw [curry_apply, TensorProduct.curry_apply, restrictScalars_apply, smul_apply, map_tmul,
214+
smul_apply, tmul_smul]
215+
216+
theorem map_smul_left (b : B) (f : M →ₗ[A] P) (g : N →ₗ[R] Q) : map (b • f) g = b • map f g := by
217+
ext
218+
simp_rw [curry_apply, TensorProduct.curry_apply, restrictScalars_apply, smul_apply, map_tmul,
219+
smul_apply, smul_tmul']
220+
221+
variable (R A B M N P Q)
222+
223+
/-- Heterobasic version of `TensorProduct.map_bilinear` -/
224+
def mapBilinear : (M →ₗ[A] P) →ₗ[B] (N →ₗ[R] Q) →ₗ[R] (M ⊗[R] N →ₗ[A] P ⊗[R] Q) :=
225+
LinearMap.mk₂' _ _ map map_add_left map_smul_left map_add_right map_smul_right
226+
227+
variable {R A B M N P Q}
228+
229+
@[simp]
230+
theorem mapBilinear_apply (f : M →ₗ[A] P) (g : N →ₗ[R] Q) :
231+
mapBilinear R A B M N P Q f g = map f g :=
232+
rfl
233+
234+
variable (R A B M N P Q)
235+
236+
/-- Heterobasic version of `TensorProduct.homTensorHomMap` -/
237+
def homTensorHomMap : ((M →ₗ[A] P) ⊗[R] (N →ₗ[R] Q)) →ₗ[B] (M ⊗[R] N →ₗ[A] P ⊗[R] Q) :=
238+
lift <| mapBilinear R A B M N P Q
239+
240+
variable {R A B M N P Q}
241+
242+
@[simp] theorem homTensorHomMap_apply (f : M →ₗ[A] P) (g : N →ₗ[R] Q) :
243+
homTensorHomMap R A B M N P Q (f ⊗ₜ g) = map f g :=
244+
rfl
245+
246+
/-- Heterobasic version of `TensorProduct.congr` -/
247+
def congr (f : M ≃ₗ[A] P) (g : N ≃ₗ[R] Q) : (M ⊗[R] N) ≃ₗ[A] (P ⊗[R] Q) :=
248+
LinearEquiv.ofLinear (map f g) (map f.symm g.symm)
249+
(ext fun _m _n => congr_arg₂ (· ⊗ₜ ·) (f.apply_symm_apply _) (g.apply_symm_apply _))
250+
(ext fun _m _n => congr_arg₂ (· ⊗ₜ ·) (f.symm_apply_apply _) (g.symm_apply_apply _))
251+
252+
@[simp] theorem congr_tmul (f : M ≃ₗ[A] P) (g : N ≃ₗ[R] Q) (m : M) (n : N) :
253+
congr f g (m ⊗ₜ n) = f m ⊗ₜ g n :=
254+
rfl
255+
256+
@[simp] theorem congr_symm_tmul (f : M ≃ₗ[A] P) (g : N ≃ₗ[R] Q) (p : P) (q : Q) :
257+
(congr f g).symm (p ⊗ₜ q) = f.symm p ⊗ₜ g.symm q :=
258+
rfl
259+
260+
end Semiring
261+
262+
section CommSemiring
263+
264+
variable [CommSemiring R] [CommSemiring A] [Semiring B] [Algebra R A] [Algebra R B]
265+
266+
variable [AddCommMonoid M] [Module R M] [Module A M] [Module B M]
267+
variable [IsScalarTower R A M] [IsScalarTower R B M] [SMulCommClass A B M]
268+
269+
variable [AddCommMonoid N] [Module R N]
270+
271+
variable [AddCommMonoid P] [Module R P] [Module A P] [Module B P]
272+
variable [IsScalarTower R A P] [IsScalarTower R B P] [SMulCommClass A B P]
273+
274+
variable [AddCommMonoid Q] [Module R Q]
275+
276+
variable (R A B M N P Q)
277+
179278
attribute [local ext high] TensorProduct.ext
180279

280+
section assoc
281+
variable [Algebra A B] [IsScalarTower A B M]
282+
181283
/-- Heterobasic version of `TensorProduct.assoc`:
182284
183-
Linear equivalence between `(M ⊗[A] N) ⊗[R] P` and `M ⊗[A] (N ⊗[R] P)`. -/
184-
def assoc : (M ⊗[A] P) ⊗[R] N ≃ₗ[A] M ⊗[A] P ⊗[R] N :=
285+
Linear equivalence between `(M ⊗[A] N) ⊗[R] P` and `M ⊗[A] (N ⊗[R] P)`.
286+
287+
Note this is especially useful with `A = R` (where it is a "more linear" version of
288+
`TensorProduct.assoc`), or with `B = A`. -/
289+
def assoc : (M ⊗[A] P) ⊗[R] Q ≃ₗ[B] M ⊗[A] (P ⊗[R] Q) :=
185290
LinearEquiv.ofLinear
186-
(lift <|
187-
TensorProduct.uncurry A _ _ _ <| comp (lcurry R A _ _ _) <| TensorProduct.mk A M (P ⊗[R] N))
188-
(TensorProduct.uncurry A _ _ _ <|
189-
comp (uncurry R A _ _ _) <| by
190-
apply TensorProduct.curry
191-
exact mk R A _ _)
192-
(by
193-
ext
194-
rfl)
195-
(by
196-
ext
197-
-- porting note: was `simp only [...]`
198-
rfl)
199-
#align tensor_product.algebra_tensor_module.assoc TensorProduct.AlgebraTensorModule.assoc
291+
(lift <| lift <| lcurry R A B P Q _ ∘ₗ mk A B M (P ⊗[R] Q))
292+
(lift <| uncurry R A B P Q _ ∘ₗ curry (mk R B _ Q))
293+
(by ext; rfl)
294+
(by ext; rfl)
295+
-- porting note: new `B` argument
296+
#align tensor_product.algebra_tensor_module.assoc TensorProduct.AlgebraTensorModule.assocₓ
297+
298+
variable {M P N Q}
299+
300+
@[simp]
301+
theorem assoc_tmul (m : M) (p : P) (q : Q) :
302+
assoc R A B M P Q ((m ⊗ₜ p) ⊗ₜ q) = m ⊗ₜ (p ⊗ₜ q) :=
303+
rfl
304+
305+
@[simp]
306+
theorem assoc_symm_tmul (m : M) (p : P) (q : Q) :
307+
(assoc R A B M P Q).symm (m ⊗ₜ (p ⊗ₜ q)) = (m ⊗ₜ p) ⊗ₜ q :=
308+
rfl
309+
310+
end assoc
311+
312+
section leftComm
313+
314+
/-- Heterobasic version of `TensorProduct.leftComm` -/
315+
def leftComm : M ⊗[A] (P ⊗[R] Q) ≃ₗ[A] P ⊗[A] (M ⊗[R] Q) :=
316+
let e₁ := (assoc R A A M P Q).symm
317+
let e₂ := congr (TensorProduct.comm A M P) (1 : Q ≃ₗ[R] Q)
318+
let e₃ := assoc R A A P M Q
319+
e₁ ≪≫ₗ e₂ ≪≫ₗ e₃
320+
321+
variable {M N P Q}
322+
323+
@[simp]
324+
theorem leftComm_tmul (m : M) (p : P) (q : Q) :
325+
leftComm R A M P Q (m ⊗ₜ (p ⊗ₜ q)) = p ⊗ₜ (m ⊗ₜ q) :=
326+
rfl
327+
328+
@[simp]
329+
theorem leftComm_symm_tmul (m : M) (p : P) (q : Q):
330+
(leftComm R A M P Q).symm (p ⊗ₜ (m ⊗ₜ q)) = m ⊗ₜ (p ⊗ₜ q) :=
331+
rfl
332+
333+
end leftComm
334+
335+
section rightComm
336+
337+
/-- A tensor product analogue of `mul_right_comm`. -/
338+
def rightComm : (M ⊗[A] P) ⊗[R] Q ≃ₗ[A] (M ⊗[R] Q) ⊗[A] P :=
339+
LinearEquiv.ofLinear
340+
(lift <| TensorProduct.lift <| LinearMap.flip <|
341+
lcurry R A A M Q ((M ⊗[R] Q) ⊗[A] P) ∘ₗ (mk A A (M ⊗[R] Q) P).flip)
342+
(TensorProduct.lift <| lift <| LinearMap.flip <|
343+
(TensorProduct.lcurry A M P ((M ⊗[A] P) ⊗[R] Q)).restrictScalars R
344+
∘ₗ (mk R A (M ⊗[A] P) Q).flip)
345+
-- explicit `Eq.refl`s here help with performance, but also make it clear that the `ext` are
346+
-- letting us prove the result as an equality of pure tensors.
347+
(TensorProduct.ext <| ext <| fun m q => LinearMap.ext <| fun p => Eq.refl <|
348+
(m ⊗ₜ[R] q) ⊗ₜ[A] p)
349+
(curry_injective <| TensorProduct.ext' <| fun m p => LinearMap.ext <| fun q => Eq.refl <|
350+
(m ⊗ₜ[A] p) ⊗ₜ[R] q)
351+
352+
variable {M N P Q}
353+
354+
@[simp]
355+
theorem rightComm_tmul (m : M) (p : P) (q : Q) :
356+
rightComm R A M P Q ((m ⊗ₜ p) ⊗ₜ q) = (m ⊗ₜ q) ⊗ₜ p :=
357+
rfl
358+
359+
@[simp]
360+
theorem rightComm_symm_tmul (m : M) (p : P) (q : Q):
361+
(rightComm R A M P Q).symm ((m ⊗ₜ q) ⊗ₜ p) = (m ⊗ₜ p) ⊗ₜ q :=
362+
rfl
363+
364+
end rightComm
365+
366+
section tensorTensorTensorComm
367+
368+
/-- Heterobasic version of `tensorTensorTensorComm`. -/
369+
def tensorTensorTensorComm :
370+
(M ⊗[R] N) ⊗[A] (P ⊗[R] Q) ≃ₗ[A] (M ⊗[A] P) ⊗[R] (N ⊗[R] Q) :=
371+
(assoc R A A (M ⊗[R] N) P Q).symm
372+
≪≫ₗ congr (rightComm R A M P N).symm (1 : Q ≃ₗ[R] Q)
373+
≪≫ₗ assoc R _ _ (M ⊗[A] P) N Q
374+
375+
variable {M N P Q}
376+
377+
@[simp]
378+
theorem tensorTensorTensorComm_tmul (m : M) (n : N) (p : P) (q : Q) :
379+
tensorTensorTensorComm R A M N P Q ((m ⊗ₜ n) ⊗ₜ (p ⊗ₜ q)) = (m ⊗ₜ p) ⊗ₜ (n ⊗ₜ q) :=
380+
rfl
381+
382+
@[simp]
383+
theorem tensorTensorTensorComm_symm_tmul (m : M) (p : P) (q : Q):
384+
(tensorTensorTensorComm R A M N P Q).symm ((m ⊗ₜ p) ⊗ₜ (n ⊗ₜ q)) = (m ⊗ₜ n) ⊗ₜ (p ⊗ₜ q) :=
385+
rfl
386+
387+
end tensorTensorTensorComm
200388

201389
end CommSemiring
202390

Mathlib/RingTheory/TensorProduct.lean

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,8 @@ variable (r : R) (f g : M →ₗ[R] N)
6060
variable (A)
6161

6262
/-- `base_change A f` for `f : M →ₗ[R] N` is the `A`-linear map `A ⊗[R] M →ₗ[A] A ⊗[R] N`. -/
63-
def baseChange (f : M →ₗ[R] N) : A ⊗[R] M →ₗ[A] A ⊗[R] N where
64-
toFun := f.lTensor A
65-
map_add' := (f.lTensor A).map_add
66-
map_smul' a x :=
67-
show
68-
(f.lTensor A) (rTensor M (LinearMap.mul R A a) x) =
69-
(rTensor N ((LinearMap.mul R A) a)) ((lTensor A f) x) by
70-
rw [← comp_apply, ← comp_apply]
71-
simp only [lTensor_comp_rTensor, rTensor_comp_lTensor]
63+
def baseChange (f : M →ₗ[R] N) : A ⊗[R] M →ₗ[A] A ⊗[R] N :=
64+
AlgebraTensorModule.map (LinearMap.id : A →ₗ[A] A) f
7265
#align linear_map.base_change LinearMap.baseChange
7366

7467
variable {A}

0 commit comments

Comments
 (0)