Lean4
/-- Define `GCDMonoid` on a structure just from the `gcd` and its properties. -/
noncomputable def gcdMonoidOfGCD [DecidableEq α] (gcd : α → α → α) (gcd_dvd_left : ∀ a b, gcd a b ∣ a)
(gcd_dvd_right : ∀ a b, gcd a b ∣ b) (dvd_gcd : ∀ {a b c}, a ∣ c → a ∣ b → a ∣ gcd c b) : GCDMonoid α :=
{ gcd
gcd_dvd_left
gcd_dvd_right
dvd_gcd := fun {_ _ _} => dvd_gcd
lcm := fun a b => if a = 0 then 0 else Classical.choose ((gcd_dvd_left a b).trans (Dvd.intro b rfl))
gcd_mul_lcm := fun a b => by
split_ifs with a0
· rw [mul_zero, a0, zero_mul]
· rw [← Classical.choose_spec ((gcd_dvd_left a b).trans (Dvd.intro b rfl))]
lcm_zero_left := fun _ => if_pos rfl
lcm_zero_right := fun a => by
split_ifs with a0
· rfl
have h := (Classical.choose_spec ((gcd_dvd_left a 0).trans (Dvd.intro 0 rfl))).symm
have a0' : gcd a 0 ≠ 0 := by
contrapose! a0
rw [← associated_zero_iff_eq_zero, ← a0]
exact associated_of_dvd_dvd (dvd_gcd (dvd_refl a) (dvd_zero a)) (gcd_dvd_left _ _)
apply Or.resolve_left (mul_eq_zero.1 _) a0'
rw [h, mul_zero] }