Zulip Chat Archive
Stream: general
Topic: type synonym instances
Jireh Loreaux (Mar 11 2022 at 17:22):
I am trying to define the (minimal) unitization of a non-unitalR
-algebra as a type synonym for R × A
. But I can't seem to get Lean to disregard the prod.has_mul
instance. What am I doing wrong here? (Note: the simp
shows that Lean is using the wrong multiplication).
import algebra.algebra.basic
def algebra.unitization (R A : Type*) [comm_ring R] [non_unital_ring A] := R × A
variables {R A : Type*} [comm_ring R] [non_unital_ring A]
open algebra
local attribute [-instance] prod.has_mul prod.has_one
instance : add_comm_group (unitization R A) := prod.add_comm_group
instance [module R A] : module R (unitization R A) := prod.module
instance : has_one (unitization R A) := { one := (1, 0) }
instance [module R A] : has_mul (unitization R A) :=
{ mul := λ ⟨r₁, a₁⟩ ⟨r₂, a₂⟩, (r₁ * r₂, r₁ • a₂ + r₂ • a₁ + a₁ * a₂) }
@[simp]
lemma one_def : (1 : unitization R A) = (1, 0) := rfl
@[simp]
lemma mul_def [module R A] (r₁ r₂ : R) (a₁ a₂ : A) :
((r₁, a₁) : unitization R A) * (r₂, a₂) = (r₁ * r₂, r₁ • a₂ + r₂ • a₁ + a₁ * a₂) :=
begin
simp,
-- ⊢ r₁ • a₂ + r₂ • a₁ = 0
sorry
end
Eric Rodriguez (Mar 11 2022 at 17:27):
firstly, the first issue is that Lean elaborates the mul as a mul of the prod
type anyways, if you look at the widget
Yaël Dillies (Mar 11 2022 at 17:28):
You might want to try making unitization
irreducible.
Jireh Loreaux (Mar 11 2022 at 17:30):
Why does it elaborate it as the prod
version if I removed that instance? I thought I would probably make unitization irreducible at the end, when I'm done with everything I need. Is that the wrong approach?
Yaël Dillies (Mar 11 2022 at 17:30):
You should use "identity" equivalences to explicitly mark the conversions
import algebra.algebra.basic
def algebra.unitization (R A : Type*) [comm_ring R] [non_unital_ring A] := R × A
variables {R A : Type*} [comm_ring R] [non_unital_ring A]
open algebra
def to_unitization : R × A ≃ unitization R A := equiv.refl _
def of_unitization : unitization R A ≃ R × A := equiv.refl _
local attribute [-instance] prod.has_mul prod.has_one
instance : add_comm_group (unitization R A) := prod.add_comm_group
instance [module R A] : module R (unitization R A) := prod.module
instance : has_one (unitization R A) := { one := (1, 0) }
instance [module R A] : has_mul (unitization R A) :=
{ mul := λ ⟨r₁, a₁⟩ ⟨r₂, a₂⟩, (r₁ * r₂, r₁ • a₂ + r₂ • a₁ + a₁ * a₂) }
@[simp]
lemma mul_def [module R A] (r₁ r₂ : R) (a₁ a₂ : A) :
to_unitization (r₁, a₁) * to_unitization (r₂, a₂) = (r₁ * r₂, r₁ • a₂ + r₂ • a₁ + a₁ * a₂) :=
sorry
Eric Rodriguez (Mar 11 2022 at 17:30):
sorry, not just the mul
, but like each individual element
Eric Rodriguez (Mar 11 2022 at 17:31):
I'm unsure why Lean does this but maybe if you set the expected type on the right, it will work out anyways (I _think_ Lean elaborates right to left, not sure)
Eric Rodriguez (Mar 11 2022 at 17:32):
wow, not even ((r₁, a₁) : unitization R A) * ((r₂, a₂): unitization R A) = ((r₁ * r₂, r₁ • a₂ + r₂ • a₁ + a₁ * a₂) : unitization R A)
works.
Jireh Loreaux (Mar 11 2022 at 17:32):
I tried before giving explicit types to all of them and it still had the same problem, but I'll use the identity equivalences.
Jireh Loreaux (Mar 11 2022 at 17:32):
yeah, that's why I was so confused.
Eric Rodriguez (Mar 11 2022 at 17:33):
((r₁, a₁) * (r₂, a₂): unitization R A) = (r₁ * r₂, r₁ • a₂ + r₂ • a₁ + a₁ * a₂)
also works, but yikes
Jireh Loreaux (Mar 11 2022 at 17:33):
But still, why doesn't local attribute [-instance] prod.has_mul
help at all?
Eric Rodriguez (Mar 11 2022 at 17:34):
because there's prod.distrib
, prod.semiring
, prod.non_assoc_semiring
.... and they all imply the has_mul
instance
Kevin Buzzard (Mar 11 2022 at 17:34):
This is probably unrelated, but generally people say "don't make definitions using λ ⟨r₁, a₁⟩ ⟨r₂, a₂⟩, ...
, instead use { mul := λ ra₁ ra₂, (ra₁.1 * ra₂.1, ra₁.1 • ra₂.2 + ra₂.1 • ra₁.2 + ra₁.2 * ra₂.2) }
"
Eric Rodriguez (Mar 11 2022 at 17:34):
you can also see this on the widgeet: image.png
Jireh Loreaux (Mar 11 2022 at 17:36):
I've never clicked on the highlight-on-hover in the widget panel :face_palm: Can't believe I've been missing this.
Kevin Buzzard (Mar 11 2022 at 17:38):
The reason it's using the wrong product is a pretty common gotcha: ((r₁, a₁) : unitization R A)
does not mean "make (r₁, a₁)
have type unitization R A
", it means "check that its type is defeq to unitization R A
but don't actually change the type unless you need to solve a unification problem"
Kevin Buzzard (Mar 11 2022 at 17:40):
The reason the (id (r₁, a₁) : unitization R A)
trick works (this is a cheap fix by the way) is that this type checking sanity thing occurs before Lean decides which \alpha
it's going to use in @id \alpha x y
, so Lean is persuaded to let alpha be unitization R A
.
Jireh Loreaux (Mar 11 2022 at 17:47):
What's the reasoning behind "don't make definitions using λ ⟨r₁, a₁⟩ ⟨r₂, a₂⟩, ...,
" ? Is it some kind of normal form issue?
Eric Rodriguez (Mar 11 2022 at 17:48):
try #print
the definition
Kevin Buzzard (Mar 11 2022 at 17:54):
Mmm, ._match_2
. The approach I suggested unfolds much better.
Eric Rodriguez (Mar 11 2022 at 17:57):
(although I will say that whenever I've done it simp!
has dealt with this sort of stuff super well)
Johan Commelin (Mar 11 2022 at 18:03):
@Jireh Loreaux If you apply it to something of the form x + 3*y
, then Lean doesn't know how to turn that into ⟨r₁, a₁⟩
automatically. So the definition will not unfold. But it doesn't have problems with (x + 3*y).1
and (x + 3*y).2
.
The reason is that foo : X × Y
is not defeq to ⟨foo.1, foo.2⟩
in Lean 3. (I think in Lean 4 this problem is gone.)
Last updated: Dec 20 2023 at 11:08 UTC