Zulip Chat Archive
Stream: new members
Topic: List of distinct elements
Iocta (Feb 13 2025 at 20:13):
How can I make a type representing list of distinct elements? Or is this unidiomatic?
inductive DistList : Type where
| empty : DistList
| cons : (x : Int) → (xs : DistList) → (not_mem : ∀ y ∈ xs, y ≠ x) → DistList
failed to synthesize
Membership ?m.2175 DistList
Kyle Miller (Feb 13 2025 at 20:16):
Idiomatic would be to define the subtype of lists whose elements are pairwise not equal:
def DistList (α : Type) : Type :=
{ xs : List α // xs.Pairwise (· ≠ ·) }
Kyle Miller (Feb 13 2025 at 20:17):
Or work with List
and carry this hypothesis around.
Kyle Miller (Feb 13 2025 at 20:19):
If you define this subtype, you'll have to define operations yourself, for example
instance {α} : Membership α (DistList α) where
mem lst x := x ∈ lst.val
It's helpful having a normalization lemma to make sure everything is in terms of this new membership operator:
@[simp] theorem DistList.mem_val_iff {α} {x : α} {lst : DistList α} :
x ∈ lst.val ↔ x ∈ lst := Iff.rfl
Edward van de Meent (Feb 13 2025 at 20:21):
you could use {xs : List α // xs.dedup = xs}
if you have DecidableEq α
Kyle Miller (Feb 13 2025 at 20:22):
(Why? What's the benefit to using that rather than the specially constructed predicate that's made for this purpose?)
suhr (Feb 13 2025 at 20:23):
Instead of using Subtype, you can just define a structure:
structure DistList (α: Type u) where
elems: List α
dist: elems.Pairwise Neq
Kyle Miller (Feb 13 2025 at 20:24):
I was just about to suggest that, since it turns out you want a constructor for the last theorem here.
structure DistList (α : Type) : Type where
toList : List α
distinct : toList.Pairwise (· ≠ ·)
instance {α} : Membership α (DistList α) where
mem lst x := x ∈ lst.toList
@[simp] theorem DistList.mem_toList_iff {α} {x : α} {lst : DistList α} :
x ∈ lst.toList ↔ x ∈ lst := Iff.rfl
@[simp] theorem DistList.mem_mk {α} {x : α} {xs : List α} {h} :
x ∈ { toList := xs, distinct := h : DistList α } ↔ x ∈ xs := Iff.rfl
Kyle Miller (Feb 13 2025 at 20:24):
(When you say "just" @suhr, do you mean that you think this is simpler? Some people would say "instead of using a custom structure, you can just define it with Subtype")
Edward van de Meent (Feb 13 2025 at 20:24):
Kyle Miller said:
(Why? What's the benefit to using that rather than the specially constructed predicate that's made for this purpose?)
you make a good point... i guess the main takeaway from my suggestion should be that docs#List.dedup exists, not that my suggestion is practical in any way.
suhr (Feb 13 2025 at 20:33):
(When you say "just" @suhr, do you mean that you think this is simpler? Some people would say "instead of using a custom structure, you can just define it with Subtype")
Not simpler, just more straightforward. And also nicer: you can choose appropriate names for fields.
Kyle Miller (Feb 13 2025 at 20:37):
What's more straightforward about defining a new type rather than re-using Subtype
, which comes with a good amount of theory already?
I agree that choosing appropriate names for fields is an improvement.
Iocta (Feb 13 2025 at 20:44):
If I do it with a subtype how do I write cons
for it (if the new head is not a member of xs
...)?
Kyle Miller (Feb 13 2025 at 20:46):
I'd suggest using structure
since that makes sure the constructor has the correct type. A painful thing you'd run into otherwise is sometimes the underlying Subtype
will pop through and make notations stop working.
Kyle Miller (Feb 13 2025 at 20:48):
structure DistList (α : Type) : Type where
toList : List α
distinct : toList.Pairwise (· ≠ ·)
instance {α} : Membership α (DistList α) where
mem lst x := x ∈ lst.toList
def DistList.cons {α} (x : α) (xs : DistList α) (h : ∀ y ∈ xs, x ≠ y) : DistList α where
toList := x :: xs.toList
distinct := by
rw [List.pairwise_cons]
exact ⟨h, xs.distinct⟩
Kyle Miller (Feb 13 2025 at 20:51):
Or you could rephrase h
to this:
def DistList.cons {α} (x : α) (xs : DistList α) (h : ¬ x ∈ xs) : DistList α where
toList := x :: xs.toList
distinct := by
obtain ⟨toList, distinct⟩ := xs
rw [List.pairwise_cons]
refine ⟨?_, distinct⟩
rintro _ h' rfl
exact h h'
Last updated: May 02 2025 at 03:31 UTC