Documentation

Mathlib.Data.SetLike.Basic

Typeclass for types with a set-like extensionality property #

The Membership typeclass is used to let terms of a type have elements. Many instances of Membership have a set-like extensionality property: things are equal iff they have the same elements. The SetLike typeclass provides a unified interface to define a Membership that is extensional in this way.

The main use of SetLike is for algebraic subobjects (such as Submonoid and Submodule), whose non-proof data consists only of a carrier set. In such a situation, the projection to the carrier set is injective.

In general, a type A is SetLike with elements of type B if it has an injective map to Set B. This module provides standard boilerplate for every SetLike: a coe_sort, a coe to set, and various extensionality and simp lemmas. The order induced by set inclusion is called PartialOrder.ofSetlike: this is not an instance for flexibility in choosing orders. The class IsConcreteLE abstractly states the order is equal to that induced by set inclusion; an instance is automatically available when defining a PartialOrder as .ofSetLike (MySubobject X) X.

A typical subobject should be declared as:

structure MySubobject (X : Type*) [ObjectTypeclass X] where
  (carrier : Set X)
  (op_mem' : ∀ {x : X}, x ∈ carrier → sorry ∈ carrier)

namespace MySubobject

variable {X : Type*} [ObjectTypeclass X] {x : X}

instance : SetLike (MySubobject X) X :=
  ⟨MySubobject.carrier, fun p q h => by cases p; cases q; congr!⟩

instance : PartialOrder (MySubobject X) := .ofSetLike (MySubobject X) X

@[simp] lemma mem_carrier {p : MySubobject X} : x ∈ p.carrier ↔ x ∈ (p : Set X) := Iff.rfl

@[ext] theorem ext {p q : MySubobject X} (h : ∀ x, x ∈ p ↔ x ∈ q) : p = q := SetLike.ext h

/-- Copy of a `MySubobject` with a new `carrier` equal to the old one. Useful to fix definitional
equalities. See Note [range copy pattern]. -/
protected def copy (p : MySubobject X) (s : Set X) (hs : s = ↑p) : MySubobject X :=
  { carrier := s
    op_mem' := hs.symm ▸ p.op_mem' }

@[simp] lemma coe_copy (p : MySubobject X) (s : Set X) (hs : s = ↑p) :
  (p.copy s hs : Set X) = s := rfl

lemma copy_eq (p : MySubobject X) (s : Set X) (hs : s = ↑p) : p.copy s hs = p :=
  SetLike.coe_injective hs

end MySubobject

An alternative to SetLike could have been an extensional Membership typeclass:

class ExtMembership (α : out_param <| Type u) (β : Type v) extends Membership α β where
  (ext_iff : ∀ {s t : β}, s = t ↔ ∀ (x : α), x ∈ s ↔ x ∈ t)

While this is equivalent, SetLike conveniently uses a carrier set projection directly.

Tags #

subobjects

class SetLike (A : Type u_1) (B : outParam (Type u_2)) :
Type (max u_1 u_2)

A class to indicate that there is a canonical injection between A and Set B.

This has the effect of giving terms of A elements of type B (through a Membership instance) and a compatible coercion to Type* as a subtype.

Note: if SetLike.coe is a projection, implementers should create a simp lemma such as

@[simp] lemma mem_carrier {p : MySubobject X} : x ∈ p.carrier ↔ x ∈ (p : Set X) := Iff.rfl

to normalize terms.

If you declare an unbundled subclass of SetLike, for example:

class MulMemClass (S : Type*) (M : Type*) [Mul M] [SetLike S M] where
  ...

Then you should not repeat the outParam declaration so SetLike will supply the value instead. This ensures your subclass will not have issues with synthesis of the [Mul M] parameter starting before the value of M is known.

Instances
    instance SetLike.instCoeTCSet {A : Type u_1} {B : Type u_2} [i : SetLike A B] :
    CoeTC A (Set B)
    Equations
      @[instance 100]
      instance SetLike.instMembership {A : Type u_1} {B : Type u_2} [i : SetLike A B] :
      Equations
        @[instance 100]
        instance SetLike.instCoeSortType {A : Type u_1} {B : Type u_2} [i : SetLike A B] :
        CoeSort A (Type u_2)
        Equations

          For terms that match the CoeSort instance's body, pretty print as ↥S rather than as { x // x ∈ S }. The discriminating feature is that membership uses the SetLike.instMembership instance.

          Equations
            Instances For
              @[simp]
              theorem SetLike.coe_sort_coe {A : Type u_1} {B : Type u_2} [i : SetLike A B] (p : A) :
              p = p
              theorem SetLike.exists {A : Type u_1} {B : Type u_2} [i : SetLike A B] {p : A} {q : pProp} :
              (∃ (x : p), q x) ∃ (x : B) (h : x p), q x, h
              theorem SetLike.forall {A : Type u_1} {B : Type u_2} [i : SetLike A B] {p : A} {q : pProp} :
              (∀ (x : p), q x) ∀ (x : B) (h : x p), q x, h
              @[simp]
              theorem SetLike.coe_set_eq {A : Type u_1} {B : Type u_2} [i : SetLike A B] {p q : A} :
              p = q p = q
              theorem SetLike.coe_ne_coe {A : Type u_1} {B : Type u_2} [i : SetLike A B] {p q : A} :
              p q p q
              theorem SetLike.ext' {A : Type u_1} {B : Type u_2} [i : SetLike A B] {p q : A} (h : p = q) :
              p = q
              theorem SetLike.ext'_iff {A : Type u_1} {B : Type u_2} [i : SetLike A B] {p q : A} :
              p = q p = q
              theorem SetLike.ext {A : Type u_1} {B : Type u_2} [i : SetLike A B] {p q : A} (h : ∀ (x : B), x p x q) :
              p = q

              Note: implementers of SetLike must copy this lemma in order to tag it with @[ext].

              theorem SetLike.ext_iff {A : Type u_1} {B : Type u_2} [i : SetLike A B] {p q : A} :
              p = q ∀ (x : B), x p x q
              @[simp]
              theorem SetLike.mem_coe {A : Type u_1} {B : Type u_2} [i : SetLike A B] {p : A} {x : B} :
              x p x p
              @[simp]
              theorem SetLike.coe_eq_coe {A : Type u_1} {B : Type u_2} [i : SetLike A B] {p : A} {x y : p} :
              x = y x = y
              @[simp]
              theorem SetLike.coe_mem {A : Type u_1} {B : Type u_2} [i : SetLike A B] {p : A} (x : p) :
              x p
              theorem SetLike.mem_of_subset {A : Type u_1} {B : Type u_2} [i : SetLike A B] {p : A} {s : Set B} (hp : s p) {x : B} (hx : x s) :
              x p
              @[simp]
              theorem SetLike.eta {A : Type u_1} {B : Type u_2} [i : SetLike A B] {p : A} (x : p) (hx : x p) :
              x, hx = x
              @[simp]
              theorem SetLike.setOf_mem_eq {A : Type u_1} {B : Type u_2} [i : SetLike A B] (a : A) :
              {b : B | b a} = a
              theorem SetLike.mem_of_subsingleton {A : Type u_1} {B : Type u_2} [i : SetLike A B] [Subsingleton B] (S : A) [h : Nonempty S] {b : B} :
              b S
              theorem SetLike.exists_not_mem_of_ne_top {A : Type u_1} {B : Type u_2} [i : SetLike A B] [LE A] [OrderTop A] (s : A) (hs : s ) (h_top : = Set.univ := by simp) :
              ∃ (b : B), bs

              If s is a proper element of a SetLike structure (i.e., s ≠ ⊤) and the top element coerces to the universal set, then there exists an element not in s.

              class IsConcreteLE (A : Type u_1) (B : outParam (Type u_2)) [SetLike A B] [LE A] :

              A class to indicate that the canonical injection between A and Set B is order-preserving.

              An instance of this class is automatically available on any partial order defined as PartialOrder.ofSetLike.

              • coe_subset_coe' {S T : A} : S T S T

                The coercion from a SetLike type preserves the ordering.

              Instances
                @[reducible]
                def LE.ofSetLike (A : Type u_1) (B : Type u_2) [SetLike A B] :
                LE A

                The order induced from a SetLike instance by inclusion.

                Equations
                  Instances For
                    @[reducible]
                    def PartialOrder.ofSetLike (A : Type u_1) (B : Type u_2) [SetLike A B] :

                    The partial order induced from a SetLike instance by inclusion.

                    A partial order defined as .ofSetLike will automatically make available an instance of IsConcreteLE.

                    Equations
                      Instances For
                        instance instIsConcreteLE (A : Type u_1) (B : Type u_2) [SetLike A B] :
                        @[simp]
                        theorem SetLike.coe_subset_coe {A : Type u_1} {B : Type u_2} [SetLike A B] [LE A] [IsConcreteLE A B] {S T : A} :
                        S T S T
                        theorem SetLike.le_def {A : Type u_1} {B : Type u_2} [SetLike A B] [LE A] [IsConcreteLE A B] {S T : A} :
                        S T ∀ ⦃x : B⦄, x Sx T
                        theorem mem_of_le_of_mem {A : Type u_1} {B : Type u_2} [SetLike A B] [LE A] [IsConcreteLE A B] {S T : A} :
                        S T∀ ⦃x : B⦄, x Sx T

                        Alias of the forward direction of SetLike.le_def.

                        @[deprecated mem_of_le_of_mem (since := "2026-01-07")]
                        theorem SetLike.GCongr.mem_of_le_of_mem {A : Type u_1} {B : Type u_2} [SetLike A B] [LE A] [IsConcreteLE A B] {S T : A} :
                        S T∀ ⦃x : B⦄, x Sx T

                        Alias of the forward direction of SetLike.le_def.


                        Alias of the forward direction of SetLike.le_def.

                        theorem SetLike.not_le_iff_exists {A : Type u_1} {B : Type u_2} [SetLike A B] [LE A] [IsConcreteLE A B] {p q : A} :
                        ¬p q xp, xq
                        @[simp]
                        theorem SetLike.coe_ssubset_coe {A : Type u_1} {B : Type u_2} [SetLike A B] [PartialOrder A] [IsConcreteLE A B] {S T : A} :
                        S T S < T
                        theorem SetLike.exists_of_lt {A : Type u_1} {B : Type u_2} [SetLike A B] [PartialOrder A] [IsConcreteLE A B] {p q : A} :
                        p < qxq, xp
                        theorem SetLike.lt_iff_le_and_exists {A : Type u_1} {B : Type u_2} [SetLike A B] [PartialOrder A] [IsConcreteLE A B] {p q : A} :
                        p < q p q xq, xp
                        @[reducible, inline]
                        abbrev SetLike.instSubtypeSet {X : Type u_3} {p : Set XProp} :
                        SetLike { s : Set X // p s } X

                        membership is inherited from Set X

                        Equations
                          Instances For
                            @[reducible, inline]
                            abbrev SetLike.instSubtype {X : Type u_3} {S : Type u_4} [SetLike S X] {p : SProp} :
                            SetLike { s : S // p s } X

                            membership is inherited from S

                            Equations
                              Instances For
                                @[simp]
                                theorem SetLike.mem_mk_set {X : Type u_3} {p : Set XProp} {U : Set X} {h : p U} {x : X} :
                                x U, h x U
                                @[simp]
                                theorem SetLike.mem_mk {X : Type u_3} {S : Type u_4} [SetLike S X] {p : SProp} {U : S} {h : p U} {x : X} :
                                x U, h x U