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

ReflectiveSubuniverse: add a couple of things and simplify one proof #1822

Merged
merged 2 commits into from
Jan 21, 2024

Conversation

jdchristensen
Copy link
Collaborator

This contains very minor changes. The main reason I'm making this an independent PR is that I have another question about typeclass resolution. I'll add a comment beside the relevant spot in the code, and will attach the verbose typeclasses debug log here.
debug.log

refine (isequiv_homotopic (O_functor f)
(O_functor_homotopy _ _ (fun x => (O_rec_beta f x)^))).
srapply (cancelL_isequiv (to O B)).
1,2: exact _. (* Why is this line needed? *)
Copy link
Collaborator Author

@jdchristensen jdchristensen Jan 20, 2024

Choose a reason for hiding this comment

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

srapply (cancelL_isequiv (to O B)). generates three goals:

?X259 : (PreReflects O B)
?X261 : (IsEquiv (to O B))
?X262 : (IsEquiv (to O B o O_rec f))

The third needs a proof (line 584), but the first two are instances. And the debug.log file shows that typeclass search finds the instances for those two, and then fails for the third (as expected). But for some reason I'm left with all three goals, instead of just the last one. Can someone explain? Earlier in the file (e.g. on line 566) the same goals are solved and stay solved.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

BTW, exactly the same thing happens with simple refine (cancelL_isequiv (to O B))., so this has nothing to do with the srapply tactic. I have also attached the less verbose version of the log, in case that is already enough to see the issue.
debug1.txt

Copy link
Collaborator Author

@jdchristensen jdchristensen Jan 21, 2024

Choose a reason for hiding this comment

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

One difference I noticed is that in the cases where something like this succeeds, the debug log has all of the top-level goals numbered as "1:". But in this case, where two solvable goals are left unsolved, the top-level goals are numbered "1:", "2:" and "3:". Maybe this indicates that Coq thinks that they are dependent in some sense, so if 3 can't be solved, it backtracks and doesn't solve 1 and 2?

And some more experimenting found that if I provide the implicit argument C, the problem goes away, with the goals all numbered "1:". But C should be clear from the provided argument to O B.

In any case, I'd like to merge this, but even after merging, if anyone can explain the behaviour to me, that would be great.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think you've correctly identified the dependency behaviour but perhaps @SkySkimmer can confirm this is the case.

Copy link
Collaborator

Choose a reason for hiding this comment

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

IDK

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@SkySkimmer Here's a standalone example that doesn't require the HoTT library. Should I create an issue on the Coq github?

Class IsEquiv {A B : Type} (f : A -> B) := foo : True.

Class Reflects (B : Type) := baz : True.

Global Instance reflects : forall B, Reflects B.
Admitted.

Definition to_O (B : Type) `{Reflects B} : B -> B.
Admitted.

Global Instance isequiv_to_O (B : Type) `{Reflects B} : IsEquiv (to_O B).
Admitted.

Definition cancelL_isequiv {A B C} (g : B -> C) {f : A -> B}
  `{IsEquiv B C g} `{IsEquiv A C (fun a => g (f a))}
  : IsEquiv f.
Admitted.

Definition isequiv_O_rec_O_inverts
       {A B : Type} (f : A -> B)
  : IsEquiv f.
Proof.
  Typeclasses eauto := debug.
  simple refine (cancelL_isequiv (to_O B)).
  1, 2: exact _. (* Coq finds these instances but then ignores them. *)
Abort.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It can be simplified a bit further:

Class IsEquiv {A B : Type} (f : A -> B) := {}.

Class Reflects (B : Type) := {}.

Definition to_O (B : Type) `{Reflects B} : B -> B.
Admitted.

Global Instance isequiv_to_O (B : Type) `{Reflects B} : IsEquiv (to_O B).
Admitted.

Definition cancelL_isequiv {A B C} (g : B -> C) {f : A -> B}
  `{IsEquiv B C g} `{IsEquiv A C (fun a => g (f a))}
  : IsEquiv f.
Admitted.

Definition isequiv_O_rec_O_inverts
       {A B : Type} `{Reflects B} (f : A -> B)
  : IsEquiv f.
Proof.
  Typeclasses eauto := debug.
  simple refine (cancelL_isequiv (to_O B)).
  1, 2: exact _. (* Coq finds these instances but then ignores them. *)
Abort.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@jdchristensen I think that would be worth reporting.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

In coq/coq#18526, it was explained that when there are dependencies between typeclass goals, earlier solutions are thrown away if later goals can't be automatically solved. I can see how this might be reasonable in some situations, but also think the behaviour I expected could be good. I also figured out that the reason that the version with (C:=O B) works is that unification solves the early typeclass goal, so it isn't part of the typeclass search. As an experiment, I tried redefining to O to take an RSU O instead of a subuniverse, so it no longer requires typeclass search. (I renamed the current to to to', and had to add primes whenever we had to O with O a subuniverse.) That allowed me to remove the annotation (C:=O B) here, but had no other effects. I thought that the library might build faster, but it was unchanged, and I thought that maybe some goals would be solved automatically, but none were. So I won't make a PR for that.

@jdchristensen jdchristensen requested a review from Alizter January 21, 2024 00:58
@jdchristensen jdchristensen merged commit 608b2d7 into HoTT:master Jan 21, 2024
23 checks passed
@jdchristensen jdchristensen deleted the RSU branch January 21, 2024 13:24
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.

3 participants