Zulip Chat Archive

Stream: Is there code for X?

Topic: membership with interval


Ka Wing Li (Dec 25 2025 at 23:36):

Discussion at #mathlib4 > Proposal: Add decidable membership for Interval

How to use interval? Tried

import Mathlib
-- def tmp := Finset.Icc 0 10
def tmp : Interval  := some { fst := 0, snd := 10, fst_le_snd := by grind}
#eval 5  tmp
/- failed to synthesize
  Decidable (5 ∈ tmp) -/

Ka Wing Li (Dec 25 2025 at 23:37):

Try to define membership

instance {α} [LE α] : Membership α (Interval α) where
  mem
  | none, _ => False
  | some ι, a => a  ι
/- failed to synthesize instance of type class
  Membership α (NonemptyInterval α) -/

Ka Wing Li (Dec 25 2025 at 23:39):

But don't we have NonemptyInterval.instMembership?

Aaron Liu (Dec 25 2025 at 23:42):

what do you want to do

Aaron Liu (Dec 25 2025 at 23:43):

can you make a #mwe

Ka Wing Li (Dec 25 2025 at 23:45):

Ka Wing Li said:

import Mathlib
-- def tmp := Finset.Icc 0 10
def tmp : Interval  := some { fst := 0, snd := 10, fst_le_snd := by grind}
#eval 5  tmp
/- failed to synthesize
  Decidable (5 ∈ tmp) -/

Is this mwe?

Robin Arnez (Dec 26 2025 at 00:04):

It seems like we're simply missing some Decidable instances:

import Mathlib

instance [Preorder α] [DecidableLE α] (x : α) (i : NonemptyInterval α) : Decidable (x  i) :=
  inferInstanceAs (Decidable (i.fst  x  x  i.snd))

instance [PartialOrder α] [DecidableLE α] (x : α) (i : Interval α) : Decidable (x  i) :=
  match i with
  |  => isFalse (by rw [ SetLike.mem_coe]; simp)
  | (a : NonemptyInterval α) => inferInstanceAs (Decidable (x  a))

def tmp : Interval  := some { fst := 0, snd := 10, fst_le_snd := by grind}

#eval 5  tmp

Ka Wing Li (Dec 26 2025 at 00:11):

Thanks!

Ka Wing Li (Dec 26 2025 at 00:11):

I am wondering whether we need Interval.instMembership as well?

Ka Wing Li (Dec 26 2025 at 00:14):

I am puzzled about the differences in the following two evals

import Mathlib

instance [Preorder α] [DecidableLE α] (x : α) (i : NonemptyInterval α) : Decidable (x  i) :=
  inferInstanceAs (Decidable (i.fst  x  x  i.snd))

instance [PartialOrder α] [DecidableLE α] (x : α) (i : Interval α) : Decidable (x  i) :=
  match i with
  |  => isFalse (by rw [ SetLike.mem_coe]; simp)
  | (a : NonemptyInterval α) => inferInstanceAs (Decidable (x  a))

def tmp : Interval  := some { fst := 0, snd := 10, fst_le_snd := by grind}

#eval 5  tmp
-- true
#eval 5  (some { fst := 0, snd := 10, fst_le_snd := by grind} : Interval )
-- false

Robin Arnez (Dec 26 2025 at 00:19):

Oh, using some is defeq abuse, it interpreted this as

#eval (5 : NonemptyInterval )  some { fst := 0, snd := 10, fst_le_snd := by grind : NonemptyInterval  }

The right way to write this is:

#check 5  ({ fst := 0, snd := 10, fst_le_snd := by grind : NonemptyInterval  } : Interval )

Ka Wing Li (Dec 26 2025 at 00:35):

I see! Thanks for clarifying.

Ka Wing Li (Dec 26 2025 at 00:44):

Okay, a simplified version

@[instance 100]
instance Interval.instMembership {α} [Preorder α] : Membership α (Interval α) where
  mem
  | , _ => False
  | (i : NonemptyInterval α), x => x  i

instance [Preorder α] [DecidableLE α] (x : α) (i : NonemptyInterval α) : Decidable (x  i) :=
  inferInstanceAs (Decidable (i.fst  x  x  i.snd))

instance [Preorder α] [DecidableLE α] (x : α) (i : Interval α) : Decidable (x  i) :=
  match i with
  |  => isFalse (by simp only [Interval.instMembership, not_false_eq_true])
  | (i : NonemptyInterval α) => inferInstanceAs (Decidable (x  i))

def tmp : Interval  := { fst := 0, snd := 10, fst_le_snd := by grind : NonemptyInterval }

#eval 5  tmp

example : 5  tmp := by
  unfold tmp
  simp only [Interval.instMembership]
  simp

Ka Wing Li (Dec 26 2025 at 00:45):

Should this be upstreamed?

Robin Arnez (Dec 26 2025 at 01:12):

Well remove the top instance though, that's an instance diamond with docs#Interval.setLike

Ka Wing Li (Dec 26 2025 at 01:18):

Sorry, I do not understand? Could you elab more?

Ka Wing Li (Dec 26 2025 at 01:19):

I am wondering about the [PartialOrder α] requirement if we use SetLike.mem_coe?

Ka Wing Li (Dec 26 2025 at 01:20):

My implementation keeps the weaker [Preorder α] requirement as in Interval definitions.

Robin Arnez (Dec 26 2025 at 12:14):

Well if you add Interval.instMembership, there will be two instance paths to e.g. Membership ℕ (Interval ℕ). The first being docs#Interval.setLike followed by docs#SetLike.instMembership and the other one being Interval.instMembership. Having two instances of the same thing is most likely a bad idea! Which is to say, I wouldn't try to generalize Interval to work with Preorders because that would require a larger refactor but rather just keep to PartialOrder.

Edward van de Meent (Dec 26 2025 at 15:39):

Note that it's only an issue if they are not definitionally equal...

Aaron Liu (Dec 26 2025 at 15:40):

defeq at reducible+instances transparency

Aaron Liu (Dec 26 2025 at 15:41):

I'm 80% sure they're defeq at default transparency if you turn off smart unfolding

Edward van de Meent (Dec 26 2025 at 15:44):

Right, but my point is that having multiple paths to deriving a certain instance is not an issue per sé. (Please do verify if the proposed instance is actually not defeq at the right transparency, as I'm on mobile right now)

Ka Wing Li (Dec 26 2025 at 15:52):

Forwarding the mathlib proposal at #mathlib4 > Proposal: Add decidable membership for Interval

Ka Wing Li (Dec 26 2025 at 16:07):

Do you mean proving this?

theorem coe_mem : a  (s : Interval α)  a  (s : Set α) := by
  simp only [instMembership, SetLike.mem_coe]
  apply Iff.intro
  · intro h
    split at h
    · exact h
    · exact h
  · intro h
    split
    · exact h
    · exact h

Aaron Liu (Dec 26 2025 at 16:12):

not proving it

Aaron Liu (Dec 26 2025 at 16:12):

proving it specifically with rfl

Aaron Liu (Dec 26 2025 at 16:18):

well more specifically by with_reducible_and_instances rfl

Ka Wing Li (Dec 26 2025 at 16:27):

Oh, I see what you mean. Recalled what definitionally equal means.

Ka Wing Li (Dec 26 2025 at 17:07):

Sadly, I endup with

theorem coe_mem (s : Interval α) : (a  s)  (a  (s : Set α)) := by
  cases s
  · rfl
  · rfl

Ka Wing Li (Dec 26 2025 at 17:09):

with_reducible_and_instances rfl doesn't work.

Ka Wing Li (Dec 26 2025 at 18:01):

However, I found that in mathlib4 NonemptyInterval.coe_coeHom is also not definitionally equal.

@[simp]
theorem coe_coeHom : (coeHom : NonemptyInterval α  Set α) = (() : NonemptyInterval α  Set α) :=
  by with_reducible_and_instances rfl
  /-
Tactic `rfl` failed: The left-hand side
  ⇑coeHom
is not definitionally equal to the right-hand side
  SetLike.coe
  -/

Aaron Liu (Dec 26 2025 at 18:03):

well that one doesn't need to be

Ka Wing Li (Dec 26 2025 at 18:03):

Excuse me, why not?

Aaron Liu (Dec 26 2025 at 18:03):

it's not an instance


Last updated: Feb 28 2026 at 14:05 UTC