Typeclass for types with a set-like extensionality property #
The has_mem
typeclass is used to let terms of a type have elements.
Many instances of has_mem
have a set-like extensionality property:
things are equal iff they have the same elements. The set_like
typeclass provides a unified interface to define a has_mem
that is
extensional in this way.
The main use of set_like
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 set_like
with elements of type B
if it
has an injective map to set B
. This module provides standard
boilerplate for every set_like
: a coe_sort
, a coe
to set, a
partial_order
, and various extensionality and simp lemmas.
A typical subobject should be declared as:
structure my_subobject (X : Type*) [object_typeclass X] :=
(carrier : set X)
(op_mem' : ∀ {x : X}, x ∈ carrier → sorry ∈ carrier)
namespace my_subobject
variables {X : Type*} [object_typeclass X] {x : X}
instance : set_like (my_subobject X) X :=
⟨my_subobject.carrier, λ p q h, by cases p; cases q; congr'⟩
@[simp] lemma mem_carrier {p : my_subobject X} : x ∈ p.carrier ↔ x ∈ (p : set X) := iff.rfl
@[ext] theorem ext {p q : my_subobject X} (h : ∀ x, x ∈ p ↔ x ∈ q) : p = q := set_like.ext h
/-- Copy of a `my_subobject` with a new `carrier` equal to the old one. Useful to fix definitional
equalities. See Note [range copy pattern]. -/
protected def copy (p : my_subobject X) (s : set X) (hs : s = ↑p) : my_subobject X :=
{ carrier := s,
op_mem' := hs.symm ▸ p.op_mem' }
@[simp] lemma coe_copy (p : my_subobject X) (s : set X) (hs : s = ↑p) :
(p.copy s hs : set X) = s := rfl
lemma copy_eq (p : my_subobject X) (s : set X) (hs : s = ↑p) : p.copy s hs = p :=
set_like.coe_injective hs
end my_subobject
An alternative to set_like
could have been an extensional has_mem
typeclass:
class has_ext_mem (α : out_param $ Type u) (β : Type v) extends has_mem α β :=
(ext_iff : ∀ {s t : β}, s = t ↔ ∀ (x : α), x ∈ s ↔ x ∈ t)
While this is equivalent, set_like
conveniently uses a carrier set projection directly.
Tags #
subobjects
- coe : A → set B
- coe_injective' : function.injective set_like.coe
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 has_mem
instance) and a compatible coercion to Type*
as a subtype.
Note: if set_like.coe
is a projection, implementers should create a simp lemma such as
to normalize terms.
Instances
- subsemigroup.set_like
- add_subsemigroup.set_like
- submonoid.set_like
- add_submonoid.set_like
- subgroup.set_like
- add_subgroup.set_like
- subsemiring.set_like
- subring.set_like
- sub_mul_action.set_like
- submodule.set_like
- subalgebra.set_like
- fractional_ideal.set_like
- topological_space.closeds.set_like
- topological_space.clopens.set_like
- topological_space.compacts.set_like
- topological_space.nonempty_compacts.set_like
- topological_space.positive_compacts.set_like
- topological_space.compact_opens.set_like
- subfield.set_like
- intermediate_field.set_like
Equations
Equations
- set_like.has_coe_to_sort = {coe := λ (p : A), {x // x ∈ p}}
Equations
- set_like.partial_order = {le := λ (H K : A), ∀ ⦃x : B⦄, x ∈ H → x ∈ K, lt := partial_order.lt (partial_order.lift coe set_like.coe_injective), le_refl := _, le_trans := _, lt_iff_le_not_le := _, le_antisymm := _}