Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ refactor ] fixes #2568; proves full symmetry for Bijection #2569

Open
wants to merge 65 commits into
base: master
Choose a base branch
from

Conversation

jamesmckinna
Copy link
Contributor

@jamesmckinna jamesmckinna commented Jan 28, 2025

A comprehensive overhaul building on the proposed refactoring in #2568 . Finally finished, I think!

UPDATED: now all 'done', and a lot tighter/smoother/cleaner

  • refactor Function.Consequences? (check implicit/explicit bindings of lemmas there, esp. in their use later)
  • BUT: full symmetry for Bijection now proved, old weaker form sym-≡ etc. now deprecated (this was a bug!)
  • AND can prove Congruent ≈₂ ≈₁ section outright under similar equational assumptions!
  • HENCE: in Function.Construct.Symmetry
    • indeed, can remove hypothesis of Congruent ≈₁ ≈₂ f from {injective|bijective}
    • hence, symmetry of IsBijective, and of Bijection, without detour via Inverse

TODO:

  • CHANGELOG
  • refactor Function.Construct.Symmetry Function.Properties.Bijection to prove full symmetry of IsBijective etc.

NB.

  • the deprecations considered in [ DRY ] Refactor Function.* to rationalise the existence of a section to a given Surjective f #2568 are optional, it's more a case of agreeing the 'right' names; existing commits make the change so as to highlight where the work has happened
  • the other changes above do necessitate deprecations, of the former, weaker (!), proofs
  • these are badged as v2.3 deprecations in favour of *WithoutCongruence constructions, but a v3.0 cleanup PR would remove the old proofs entirely and rename to remove that suffix
  • not entirely sure I've quite got the deprecation messages correct, given how gnarly the refactoring has been.... it's typically not a straightforward like-for-like deprecation, because the types have changed
  • likewise, there may still be one or two outstanding DRY opportunities for further refactoring, but downstream!

@jamesmckinna jamesmckinna changed the title [ refactor ] fixes #2568 [ refactor ] fixes #2568; proves symmetry for Bijection Jan 29, 2025
@jamesmckinna jamesmckinna marked this pull request as ready for review January 29, 2025 16:24
@jamesmckinna jamesmckinna added this to the v2.3 milestone Jan 29, 2025
@jamesmckinna jamesmckinna changed the title [ refactor ] fixes #2568; proves symmetry for Bijection [ refactor ] fixes #2568; proves full symmetry for Bijection Jan 29, 2025
CHANGELOG.md Outdated
Comment on lines 149 to 152
* In `Function.Consequences`: the theory of the left inverse of a surjective function
```agda
module Section (surj : Surjective ≈₁ ≈₂ f)
```
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should this module be lifted out from Consequences to the top-level of Function.*? Or somewhere else?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Given that the only property used in the Section module is surjective⇒strictlySurjective, it is tempting to inline that, against lifting out the whole module, and deprecating Function.Consequences.* entirely, as those properties are nowhere else used in stdlib? ... downstream PR... ?

Copy link
Contributor Author

@jamesmckinna jamesmckinna Feb 7, 2025

Choose a reason for hiding this comment

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

Hmmm... not 'nowhere':

Comment on lines 36 to 46
module _ (≈₁ : Rel A ℓ₁) (≈₂ : Rel B ℓ₂) {f : A B} {f⁻¹ : B A} where

inverseʳ : Inverseˡ ≈₁ ≈₂ f f⁻¹ Inverseʳ ≈₂ ≈₁ f⁻¹ f
inverseʳ inv = inv
inverseʳ = id

inverseˡ : Inverseʳ ≈₁ ≈₂ f f⁻¹ Inverseˡ ≈₂ ≈₁ f⁻¹ f
inverseˡ inv = inv
inverseˡ = id

inverseᵇ : Inverseᵇ ≈₁ ≈₂ f f⁻¹ Inverseᵇ ≈₂ ≈₁ f⁻¹ f
inverseᵇ (invˡ , invʳ) = (invʳ , invˡ)
inverseᵇ = swap

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's tempting to want to deprecate/remove this whole section, else move to Function.Consequences.
In any case, the use of the lemmas in this module has been inlined away, against such a move.

@@ -20,16 +20,16 @@
module Function.Bundles where

open import Function.Base using (_∘_)
open import Function.Consequences.Propositional
using (strictlySurjective⇒surjective; strictlyInverseˡ⇒inverseˡ; strictlyInverseʳ⇒inverseʳ)
Copy link
Contributor Author

@jamesmckinna jamesmckinna Feb 7, 2025

Choose a reason for hiding this comment

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

It is tempting to want to inline these, as, in the Propositional case, they each take on a particularly simple form which is obscured by the three levels of indirection in these definitions...

Copy link
Contributor

Choose a reason for hiding this comment

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

inline these where?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Firstly, in Function.Consequences.Propositional (see latest commit), but one could even imagine inlining these definitions (given how simple they are) at any call-site...?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Last words on this:

  • I think it is better, given that the types of the corresponding lemmas in Function.Consequences.Propositional differ from those in Function.Consequences{.Setoid} (by making f explicit), we can, moreover should, feel free to reimplement them, as is now done;
  • the explicit quantification seems necessary in the handful of call-sites where these lemmas are actually used (and with enough of them, that I no longer propose inlining them there)...
  • ... BUT is wrong for strictlyInverseʳ⇒inverseʳ where it is f⁻¹ which should be supplied explicitly, and not f! Fixing this should form part of [ DRY ] Streamline Function.* hierarchy #2570

Copy link
Contributor

@JacquesCarette JacquesCarette left a comment

Choose a reason for hiding this comment

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

Spectacular work. Just one question and one nitpick.

@@ -20,16 +20,16 @@
module Function.Bundles where

open import Function.Base using (_∘_)
open import Function.Consequences.Propositional
using (strictlySurjective⇒surjective; strictlyInverseˡ⇒inverseˡ; strictlyInverseʳ⇒inverseʳ)
Copy link
Contributor

Choose a reason for hiding this comment

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

inline these where?

@@ -23,22 +24,22 @@ private
a b ℓ₁ ℓ₂ : Level
A B : Set a
≈₁ ≈₂ : Rel A ℓ₁
f f⁻¹ : A → B
to f f⁻¹ : A → B
Copy link
Contributor

Choose a reason for hiding this comment

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

I understand that the way variables work, this declaration of f and f⁻¹ will actually have the 'right' things in practice, I find the declaration here confusion, i.e. I would prefer an additional line with f⁻¹ : B → A for clarity.

And I thought you'd rename f to to and f⁻¹ to from everywhere?

Copy link
Contributor Author

@jamesmckinna jamesmckinna Feb 8, 2025

Choose a reason for hiding this comment

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

Re: variables.
You're absolutely right. Much clearer for ux/ergonomic reasons, and the typechecker needn't care!

Re: inlining.
Two things about this:

  • I'd thought these lemmas weren't used quite as much as they are (I was really focused on their use in Function.*), so the case for inlining is less strong now
  • that said, the Function.Consequences.Propositional version probably should be inlined/redefined in that module, because in that setting, the way cong and trans are defined for _≡_ means that they take a much simpler form than that inheriting from Setoid...

Re: f and f⁻¹.
I'd thought to have to and from for the new uses (and not simply those in Structures/Bundles), but I'm not really a fan of 'gratuitous' alpha-conversion elsewhere, if only for the sake of keeping the footprint of the PR smaller. But I could be persuaded... ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants