Zulip Chat Archive

Stream: mathlib4

Topic: Ring instance


Martin Dvořák (Sep 08 2023 at 09:00):

This is my first time playing with algebraic structures in Lean 4.
I decided to define a custom Ring instance over rational numbers.
I thought it would be an easy exercise (it probably is -- and I seem to be n00b).

import Mathlib.Data.Rat.Defs

def weirdAdd (a b : ) :  := a + b - 1/2
def weirdMul (a b : ) :  := a + b + 2*a*b

instance : Ring  where
  add := weirdAdd
  mul := weirdMul
  zero := 1/2
  neg := fun x => 1 - x
  one := 0
  zero_add := sorry
  add_zero := sorry
  add_left_neg := sorry
  one_mul := sorry
  mul_one := sorry
  zero_mul := sorry
  mul_zero := sorry
  add_comm := sorry
  add_assoc := sorry
  mul_assoc := sorry
  left_distrib := sorry
  right_distrib := sorry

I already have an error:

type mismatch
  HEq.rfl
has type
  HEq ?m.1052 ?m.1052 : Prop
but is expected to have type
  NatCast.natCast 0 = 0 : Prop

What is the cause? Do I need to provide the natCast function, prove natCast_zero and so on?

Eric Wieser (Sep 08 2023 at 09:01):

You would do better to do this exercise on a (wrapped) copy of the rational numbers

Eric Wieser (Sep 08 2023 at 09:02):

structure MyRat where
  val : Rat


def weirdAdd (a b : MyRat) : MyRat := .mk (a.val + b.val - 1/2)
def weirdMul (a b : MyRat) : MyRat := .mk (a.val + b.val + 2*a.val*b.val)

instance : Ring MyRat where

Eric Wieser (Sep 08 2023 at 09:02):

Otherwise Lean will try to use the existing instance, which is what is going wrong here

Martin Dvořák (Sep 08 2023 at 09:03):

Would def Q' : Type := ℚ be enough? Or does it have to be a structure with a rational field?

Eric Wieser (Sep 08 2023 at 09:03):

That would be enough, but it's much easier to make a mess

Eric Wieser (Sep 08 2023 at 09:03):

If you use that approach, you will want to to define Q'.mk and Q.val manually, and write your code as if you were using a structure

Martin Dvořák (Sep 08 2023 at 09:28):

How can I unfold the zero now?

import Mathlib.Data.Rat.Defs

structure ℚ' where
  v : 

def weirdAdd (a b : ℚ') : ℚ' := .mk$ a.v + b.v - (1/2 : )
def weirdMul (a b : ℚ') : ℚ' := .mk$ a.v + b.v + (2 : ) * a.v * b.v

instance weirdRing : Ring ℚ' where
  add := weirdAdd
  mul := weirdMul
  zero := .mk (1/2 : )
  neg := (fun (x : ℚ') => .mk (1 - x.v))
  one := .mk 0
  zero_add (x : ℚ') := by
    --unfold HAdd.hAdd
    --unfold instHAdd
    --unfold weirdAdd
    --unfold Add.add
    simp only [HAdd.hAdd, instHAdd, weirdAdd, Add.add]
    -- `0.v` is `@OfNat.ofNat ℚ' 0 Zero.toOfNat0 : ℚ'`
    sorry
  add_zero := sorry
  add_left_neg := sorry
  one_mul := sorry
  mul_one := sorry
  zero_mul := sorry
  mul_zero := sorry
  add_comm := sorry
  add_assoc := sorry
  mul_assoc := sorry
  left_distrib := sorry
  right_distrib := sorry

Is there a better way how to get from the generic goal 0 + x = x to working with my definitions?

Eric Wieser (Sep 08 2023 at 09:33):

Put @[simps] on your defs?

Eric Wieser (Sep 08 2023 at 09:34):

(and ext on the structure)

Martin Dvořák (Sep 08 2023 at 09:37):

Did I understand your recommendation right?

import Mathlib.Data.Rat.Defs

@[ext]
structure ℚ' where
  v : 

@[simps]
def weirdAdd (a b : ℚ') : ℚ' := .mk$ a.v + b.v - (1/2 : )

@[simps]
def weirdMul (a b : ℚ') : ℚ' := .mk$ a.v + b.v + (2 : ) * a.v * b.v

instance weirdRing : Ring ℚ' where
  add := weirdAdd
  mul := weirdMul
  zero := .mk (1/2 : )
  neg := fun x => .mk (1 - x.v)
  one := .mk 0
  zero_add (x : ℚ') := by
    --simp only [HAdd.hAdd, instHAdd, weirdAdd, Add.add]
    simp -- has no effect
    sorry
  add_zero := sorry
  add_left_neg := sorry
  one_mul := sorry
  mul_one := sorry
  zero_mul := sorry
  mul_zero := sorry
  add_comm := sorry
  add_assoc := sorry
  mul_assoc := sorry
  left_distrib := sorry
  right_distrib := sorry

It has no effect.

Eric Wieser (Sep 08 2023 at 09:44):

The ext attribute won't do anything until you use the corresponding tactic

Eric Wieser (Sep 08 2023 at 09:45):

Defining neg and zero separately with simps will help too

Martin Dvořák (Sep 08 2023 at 09:55):

Still no unfolding.

import Mathlib.Data.Rat.Defs

@[ext]
structure ℚ' where
  v : 

@[simps]
def weirdAdd (a b : ℚ') : ℚ' := .mk$ a.v + b.v - (1/2 : )

@[simps]
def weirdMul (a b : ℚ') : ℚ' := .mk$ a.v + b.v + (2 : ) * a.v * b.v

@[simps]
def weirdZero : ℚ' := .mk$ 1 / 2

@[simps]
def weirdOne : ℚ' := .mk 0

@[simps]
def weirdNeg (a : ℚ') : ℚ' := .mk$ 1 - a.v

instance weirdRing : Ring ℚ' where
  add := weirdAdd
  mul := weirdMul
  zero := weirdZero
  neg := weirdNeg
  one := weirdOne
  zero_add (x : ℚ') := by
    --ext -- goes too far
    simp -- has no effect
    sorry
  add_zero := sorry
  add_left_neg := sorry
  one_mul := sorry
  mul_one := sorry
  zero_mul := sorry
  mul_zero := sorry
  add_comm := sorry
  add_assoc := sorry
  mul_assoc := sorry
  left_distrib := sorry
  right_distrib := sorry

Is there any tutorial that I could follow?
I cannot be the first one who struggles with these instances.

Eric Wieser (Sep 08 2023 at 10:02):

ext : 1 will go exactly as far as you need

Eric Wieser (Sep 08 2023 at 10:04):

here is an exercise that has you build this type of type alias

Martin Dvořák (Sep 08 2023 at 12:19):

Very nice tutorial, thank you!

Martin Dvořák (Sep 08 2023 at 14:56):

I finished my exercise:
https://github.com/madvorak/lean4-exercises/blob/main/Rings.lean

  • It took me longer than I expected. However, this is indicative of me being a n00b, not of Lean 4 not being user-friendly.
  • I didn't manage to do the proofs inside the instance declaration; I might possibly define a notation before declaring the instance and use it in all lemmas, but it is not what I hoped for.
  • On the positive side, Lean proved to be a proof assistant. I made a mathematical mistake originally. In Lean, it was easy to find the mistake and very fast to correct it.

Martin Dvořák (Sep 08 2023 at 15:08):

I would really like to know how to write it so that I will be able open the tactic mode inside the instance declaration and unfold my definitions there. Repeating each condition in a separate lemma statement was annoying.


Last updated: Dec 20 2023 at 11:08 UTC