Zulip Chat Archive

Stream: lean4

Topic: DecidableEq, LT, GT


André Luiz Feijó dos Santos (Sep 26 2025 at 20:19):

I've been struggling to define DecidableEq, LT, and LE instances for "non-direct" notions of equality — that is, equality different from the default, where, for example, in this post, monday = monday and wednesday = wednesday.

Suppose I want to define NumQ, which is rational -- like:

inductive NumQ where
| rat : Int -> Nat -> NumQ -- "rat num den"

where I want DecidableEq, LT and LE to consider the comparison by cross multiplication to say that, e.g.:

(rat 3 4 = rat 30 40) = true.

How should I define DecidableEq, LT, and LE for NumQ in this way?

Aaron Liu (Sep 26 2025 at 20:21):

for decidableeq you need to take a quotient

André Luiz Feijó dos Santos (Sep 26 2025 at 20:23):

Thanks for answering. Could you give me an example of how to implement it?

Aaron Liu (Sep 26 2025 at 20:24):

inductive NumQ : Type where
| rat : Int -> Nat -> NumQ -- "rat num den"

open NumQ

-- actually it doesn't work like that
example : rat 3 4  rat 30 40 := by simp

Aaron Liu (Sep 26 2025 at 20:26):

André Luiz Feijó dos Santos said:

Thanks for answering. Could you give me an example of how to implement it?

well Batteries does docs#Rat differently (it reduces the fractions) and usually we don't like to use Quotient if there's a way to efficiently pick a representative from each equivalence class

Aaron Liu (Sep 26 2025 at 20:26):

since it breaks canonicity

Robin Arnez (Sep 26 2025 at 22:07):

If you want to still know how quotients work:

inductive PreNumQ : Type where
  | rat : Int  Nat  PreNumQ -- "rat num den"

def PreNumQ.Eqv (x y : PreNumQ) : Prop :=
  match x, y with
  | .rat a b, .rat c d =>
    sorry -- what you want rat a b = rat c d to mean

instance PreNumQ.setoid : Setoid PreNumQ where
  r := PreNumQ.Eqv
  iseqv := { -- proof that it is an equivalence relation
    refl x := sorry
    symm {x y} h := sorry
    trans {x y z} h h' := sorry
  }

def NumQ := Quotient PreNumQ.setoid
def NumQ.rat (a : Int) (b : Nat) : NumQ := Quotient.mk _ (.rat a b)

theorem NumQ.rat_eq_rat_iff {a b c d} : rat a b = rat c d  PreNumQ.Eqv (.rat a b) (.rat c d) :=
  Quotient.exact, Quotient.sound (s := PreNumQ.setoid)

Kenny Lau (Sep 26 2025 at 22:59):

@André Luiz Feijó dos Santos the key concept here is that while < and <= are relations that can be defined arbitrarily, = is actually a core notion of Lean that cannot be changed

François G. Dorais (Sep 27 2025 at 05:15):

In addition to the previous responses, note that == (aka BEq) can be defined arbitrarily. It is, however, required to be decidable since its value is in Bool instead of Prop.

Robert Maxton (Sep 27 2025 at 08:56):

higher inductives when :(

David Thrane Christiansen (Sep 28 2025 at 00:22):

The reference manual explains quotient types and gives some related examples, in case that's useful.


Last updated: Dec 20 2025 at 21:32 UTC