Last time we built the integers MyInt as equivalence classes over MyNat. This time we define subtraction on MyInt, and then register MyInt as an instance of Mathlib's abelian group class AddCommGroup so that the laws we've already proven can be reused. This article follows ゼロから始めるLean言語入門 手を動かして学ぶ形式数学ライブラリ開発.
Defining subtraction
Subtraction on the integers can be defined by adding the additive inverse. We define MyInt.sub and register it as the Sub instance. We also prove sub_def, showing that x - y equals x + -y, and mark it simp so it can be used for rewriting.
def MyInt.sub (m n : MyInt) : MyInt := m + -n
instance : Sub MyInt where
sub := MyInt.sub
@[notation_simp, simp]
theorem MyInt.sub_def (x y : MyInt) : x -y = x + -y := rfl
We also prove neg_add_cancel, which shows that an element cancels with its additive inverse. Unfolding the definition with unfold_int₁ and then calling ac_rfl closes the goal.
theorem MyInt.neg_add_cancel (m : MyInt) : -m + m = 0 := by
revert m
unfold_int₁
ac_rfl
Registering MyInt as an AddCommGroup
Registering MyInt as an instance of Mathlib's AddCommGroup lets us use Mathlib's lemmas and tactics for abelian groups directly. nsmul and zsmul represent multiplication by a natural number and by an integer respectively, and we pass the default implementations nsmulRec and zsmulRec for them. The laws we've already proven, such as add_assoc and add_comm, can simply be passed in as the remaining fields.
instance : AddCommGroup MyInt where
add_assoc := MyInt.add_assoc
add_comm := MyInt.add_comm
zero_add := MyInt.zero_add
add_zero := MyInt.add_zero
neg_add_cancel := MyInt.neg_add_cancel
nsmul := nsmulRec
zsmul := zsmulRec
Using the abel tactic
Now that MyInt is registered as an AddCommGroup, we can use the abel tactic, which handles equalities in abelian groups automatically.
example (a b : MyInt) : (a + b) - b = a := by
abel
Resolving a conflict with the ⟦⟧ notation
After importing Mathlib, the ⟦⟧ notation we defined for Quotient.mk can conflict with Mathlib's own notation. This can be avoided by making the notation scoped and confining it to the PreInt namespace.
namespace PreInt
scoped notation "⟦" a "⟧" => Quotient.mk PreInt.sr a
end PreInt
open scoped PreInt
The code for this article is available in the repository below.
https://github.com/ringring-creator/LearnLean