Skip to content
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ New modules

* `Data.List.Relation.Binary.Permutation.Declarative{.Properties}` for the least congruence on `List` making `_++_` commutative, and its equivalence with the `Setoid` definition.

* `Relation.Binary.Construct.SetoidFromPartialSetoid`.

Additions to existing modules
-----------------------------

Expand Down
58 changes: 58 additions & 0 deletions src/Relation/Binary/Construct/SetoidFromPartialSetoid.agda
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
------------------------------------------------------------------------
-- The Agda standard library
--
-- Conversion of a PartialSetoid into a Setoid
------------------------------------------------------------------------

open import Relation.Binary.Bundles using (PartialSetoid; Setoid)

module Relation.Binary.Construct.SetoidFromPartialSetoid
{a ℓ} (S : PartialSetoid a ℓ) where

open import Function.Base using (id; _on_)
open import Level using (_⊔_)
open import Relation.Binary.Core using (Rel)
open import Relation.Binary.Structures
using (IsEquivalence)
open import Relation.Binary.Morphism.Structures
using (IsRelHomomorphism; IsRelMonomorphism)

private
module S = PartialSetoid S


------------------------------------------------------------------------
-- Definitions

record Carrier : Set (a ⊔ ℓ) where
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I must say that I expected the carrier to be called Carrier (and not ι) with the record called something like 'Reflective' or some such.

Thinking some more, I think having a definition for Defined x (expanding to x S.≈ x) might make the overall definition more perspicuous.

Copy link
Contributor Author

@jamesmckinna jamesmckinna Sep 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So...

  • Carrier (capitalised) is the carrier type; did you envisage carrier (lower-case) for the name of its inhabitant?
    I was motivated by my proposal under Substructures and quotients in the Algebra.* hierarchy #1899 to have a standardised name which then becomes the underlying function of the homo-/mono-morphism injecting Carrier into S.Carrier... but part of my thinking was also that the record itself doesn't merit an 'interesting' name... because it should only be exposed through its Setoid API, when it would moreover, again receive the name Carrier... (and be renamed, presumably, at any client use-site, if needed)
  • adding Defined sounds a good suggestion for Relation.Binary.Definitions... DRY says we should then redefine Reflexive in terms of it?

On naming, I think I was struck looking back over #2071 that the carrier type of the symmetric interior is given an 'interesting'/'informative' name, when in fact that's another case (I now think), where the record type is a concrete implementation detail which should only really be accessed/accessible via the API for the Construct being defined... esp. given that the module import path already cues the construction as that of the symmetric interior...

UPDATED: I've gone back over that last paragraph, and it doesn't any longer make sense!? Sorry for the noise!

Let me retry :
#2071 defines a construction on binary relations, not on types, whereas Carrier constructs a type towards building a Setoid, so it's not obvious that it belongs under Construct?

The operating construct on binary relations involved here is simply _on_, but I'd hesitate before putting the derived constructions as Properties of Relation.Binary.Construct.On...?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

D'oh!?

I've ended up defining
subset = equaliser of kernel pair
for a/the special case of the 'inclusion'...

So it is probably better to refactor this as
kernel pair of arbitrary function (Fam again!?), and then specialise that at id?

Or: take a breath and sit on my hands for a bit...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good realization - I certainly had not spotted that. Perhaps sitting is indeed wise.


field
ι : S.Carrier
refl : ι S.≈ ι

open Carrier public using (ι)

_≈_ : Rel Carrier _
_≈_ = S._≈_ on ι

-- Structure

isEquivalence : IsEquivalence _≈_
isEquivalence = record
{ refl = λ {x = x} → Carrier.refl x
; sym = S.sym
; trans = S.trans
}

-- Bundle

setoid : Setoid _ _
setoid = record { isEquivalence = isEquivalence }

-- Monomorphism

isRelHomomorphism : IsRelHomomorphism _≈_ S._≈_ ι
isRelHomomorphism = record { cong = id }

isRelMonomorphism : IsRelMonomorphism _≈_ S._≈_ ι
isRelMonomorphism = record { isHomomorphism = isRelHomomorphism ; injective = id }