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

Agda 2.6.4 #9

Merged
merged 5 commits into from
Feb 18, 2024
Merged

Agda 2.6.4 #9

merged 5 commits into from
Feb 18, 2024

Conversation

jkopanski
Copy link
Contributor

@jkopanski jkopanski commented Jan 17, 2024

Intro

With this Agda version there were changes [1] to instance resolution
algorithm, from agda changelog:

[Breaking] The algorithm for resolution of instance arguments has been
simplified. It will now only rely on the type of instances to
determine which candidate it should use, and no longer on their
values.

I've found this thread [2] at zulip, which might be helpful. It
wasn't for me;)

Solution

In the end I've removed the opening of the Equivalent record module
straight after its definition. With this version Agda won't be able
to figure out definitions like this:

F-cong :  {a b} {f g : a ⇨ b}  f ≈ g  Fₘ f ≈ Fₘ g

where each _≈_ belongs to a different instance. That's why now one
have to manually open appropriate instance. However if we have only
single Equivalent in the context using an open Equivalent ⦃ … ⦄
will suffice.

Additional comments around design

Furthermore I've added explicit implicit ;) arguments to Equivalent
fields. Those are actually important and it is impossible to follow
hint that was stated in the TODO comment, that used to said:

TODO: move a and b arguments from methods to record.

Without those implicit args, definitions like:

∘≈ :  {f g : a ⇨ b} {h k : b ⇨ c}  h ≈ k  f ≈ g  h ∘ f ≈ k ∘ g

wouldn't typecheck as the Equivalent would lock it's variables
during instantiation and we could use only those two (a & b in
this case). _≈_ would reject morphisms h & k here as it's
objects would be different.

There is additional TODO comment that says:

TODO: Replace Equivalent by Setoid?

Actually moving variables mentioned above would almost turn Equivalent
into Setoid (minus Carrier as a field). Which isn't really feasible
for the reasons already mentioned.

How others do it

I've took a peek how agda-categoris does it [3] and they basically put
Equivalent into definition of Category and call it Setoid
enriched
. I've played with that for a bit. Initially putting _≈_
into lawful category. That didn't work out however because we need
_≈_ for defining different kinds homomorphisms, where we don't have
lawful classes in scope. So I've moved it to the raw Category, but
the problem with definitions that use multiple equalities still
persists. I think that restricting the opening of Category class
would be too cumbersome. So I think this split to Equivalent works
nice. I do wonder however if it's worth doing the instance search, if
most of the time one has to manually open appropriate one?

[1] https://github.com/agda/agda/blob/master/doc/release-notes/2.6.4.md#language
[2] https://agda.zulipchat.com/#narrow/stream/238741-general/topic/Issue.20with.20instance.20search.20changes.20in.202.2E6.2E4/near/384560563
[3] https://github.com/agda/agda-categories/blob/master/src/Categories/Category/Core.agda#L21

@jkopanski jkopanski marked this pull request as ready for review January 25, 2024 21:58
@conal
Copy link
Owner

conal commented Feb 11, 2024

With this version Agda won't be able to figure out definitions like this:

F-cong :  {a b} {f g : a ⇨ b}  f ≈ g  Fₘ f ≈ Fₘ g

where each _≈_ belongs to a different instance.

Do you understand how it is that the new restriction on instance selection applies to this F-cong signature? Doesn't this code rely on the morphism types rather values to determine each of the two Equivalent instances needd?

@jkopanski
Copy link
Contributor Author

With this version Agda won't be able to figure out definitions like this:

F-cong :  {a b} {f g : a ⇨ b}  f ≈ g  Fₘ f ≈ Fₘ g

where each _≈_ belongs to a different instance.

Do you understand how it is that the new restriction on instance selection applies to this F-cong signature? Doesn't this code rely on the morphism types rather values to determine each of the two Equivalent instances needd?

just a caveat that my understanding of this is very limited!

But the _≈_ type itself sits inside a record and now Agda won't look inside of that record.

I think we should look into the change PR for more clues. Specifically take a look at test cases: Issue1952 they seem to contain some similar signatures that we would like to have.

@conal
Copy link
Owner

conal commented Feb 11, 2024

But the _≈_ type itself sits inside a record and now Agda won't look inside of that record.

Thank you. I'll do some experimenting also.

Comment on lines 35 to 37
infix 2 ⟺
: {f g : a ⇨ b} → f ≈ g → gf
= sym
Copy link
Owner

Choose a reason for hiding this comment

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

What motivated introducing and using this synonym for sym? Is it related to the other changes in this PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, this pointed out that I didn't spell out my bigger questions here. Right now the we open Equiv publicly, under the Equivalent. Using sym (and refl, trans) directly will have the problems we are seeing. I think that we shouldn't reexport those functions publicly, but I didn't want to change that without discussing.

That's why I introduced alias for sym which comes from ≈-Reasoning module and can have Equivalent instance passed explicitly.

Alias itself and its fixity declarations come from agda- categories and I don't know the answer to the fixity question.

Another approach would be to reexport familiar names from the reasoning module instead.

Copy link
Owner

Choose a reason for hiding this comment

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

Thank you for the context. I had not noticed that you moved _;_ and _•_ under ≈-Reasoning. Nice trick!

I agree with you about reexporting refl, sym, and trans from ≈-Reasoning instead of from Equivalent. Thanks for the suggestion.

infixr 9 _•_
_•_ : {f g h : a ⇨ b} (g≈h : g ≈ h) (f≈g : f ≈ g) → f ≈ h
g≈h • f≈g = trans f≈g g≈h
infix 2 ⟺
Copy link
Owner

Choose a reason for hiding this comment

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

What is the effect of an infix declaration for an operator without one or more underscores in its name?

@conal
Copy link
Owner

conal commented Feb 16, 2024

The single essence of this PR is to open ≈-Reasoning with an explicit Equivalence argument, in order to disambiguate refl, sym, and trans (and their synonyms), right?

@jkopanski
Copy link
Contributor Author

The single essence of this PR is to open ≈-Reasoning with an explicit Equivalence argument, in order to disambiguate refl, sym, and trans (and their synonyms), right?

yes, although only synonyms will be disambiguated, because refl, sym, and trans are opened publicly outside of the ≈-Reasoning.

With this Agda version there were changes [1] to instance resolution
algorithm, from agda changelog:

[Breaking] The algorithm for resolution of instance arguments has been
simplified. It will now only rely on the type of instances to
determine which candidate it should use, and no longer on their
values.

I've found this thread [2] at zulip, which might be helpful, but I
don't know how to fix the issues at felix yet.

[1] https://github.com/agda/agda/blob/master/doc/release-notes/2.6.4.md#language
[2] https://agda.zulipchat.com/#narrow/stream/238741-general/topic/Issue.20with.20instance.20search.20changes.20in.202.2E6.2E4/near/384560563
This reverts commit 6df31ea.
Furthermore I've added explicit implicit ;) arguments to `Equivalent`
fields.  Those are actually important and it is impossible to follow
hint that was stated in the `TODO` comment, that used to said:

> TODO: move a and b arguments from methods to record.

Without those implicit args, definitions like:

```agda
∘≈ : ∀ {f g : a ⇨ b} {h k : b ⇨ c} → h ≈ k → f ≈ g → h ∘ f ≈ k ∘ g
```

wouldn't typecheck as the `Equivalent` would lock it's variables
during instantiation and we could use only those two (`a` & `b` in
this case). `_≈_` would reject morphisms `h` & `k` here as it's
objects would be different.

There is additional `TODO` comment that says:

> TODO: Replace Equivalent by Setoid?

Actually moving variables mentioned above would almost turn Equivalent
into Setoid (minus `Carrier` as a field).  Which isn't really feasible
for the reasons already mentioned.

I've took a peek how agda-categoris does it [3] and they basically put
`Equivalent` into definition of `Category` and call it _Setoid
enriched_.  I've played with that for a bit.  Initially putting `_≈_`
into lawful category.  That didn't work out however because we need
`_≈_` for defining different kinds homomorphisms, where we don't have
lawful classes in scope.  So I've moved it to the raw `Category`, but
the problem with definitions that use multiple equalities still
persists.  I think that restricting the opening of `Category` class
would be too cumbersome.  So I think this split to `Equivalent` works
nice.  I do wonder however if it's worth doing the instance search, if
most of the time one has to manually open appropriate one?

I've also updated the readme to reflect supported versions.

[3] https://github.com/agda/agda-categories/blob/master/src/Categories/Category/Core.agda#L21
Turns out agda can infer proper Equivalent typeclass from the use of
`_≈_`, based on the arguments.  What is problematic are the implicit
arguments to the `trans`, `sym` (and `refl`).  But those are used in
the proofs.  I've noticed that agda-categories [1] put those operators
inside their equivalent of `≈-Reasoning` which can (even have to) be
opened independently of `Equivalent`.  This way we can keep
`Equivalent` open in `public` and enjoy nice definitions.  What we
need to do is a little extra work of opening `≈-Reasoning` with proper
Equivalent instance as parameter.

In order to signify the change standard functions were renamed:
- refl to refl≈
- sym to sym≈
- trans to _;_

I didn't removed flipped trans (_•_) as there were some uses of it in
the code.  We can remove them separately if that'll be deemed
necessary.

[1] https://github.com/agda/agda-categories/blob/master/src/Categories/Category/Core.agda#L90
@conal conal merged commit ac42c5f into conal:main Feb 18, 2024
1 check passed
@conal
Copy link
Owner

conal commented Feb 18, 2024

Thank you, @jkopanski, for all your effort in adapting Felix to Agda 2.6.4. I'm delighted with the result! We're back in the mainstream of Agda progress, while retaining readability, especially in the signatures/theorems, where it matters most!

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

Successfully merging this pull request may close these issues.

2 participants