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

Explanation about bidirectionality hints #71

Merged
merged 1 commit into from
Jan 31, 2025

Conversation

Lysxia
Copy link
Contributor

@Lysxia Lysxia commented Nov 3, 2024

I think it's an explanation rather than a tutorial but I'll be happy to defer to you if you think otherwise.

@thomas-lamiaux
Copy link
Collaborator

I am going to ask @MevenBertrand to review as he is a specialist of bidirectional typechecking.
He is quite busy at the moment, so I am not sure when he'll have the time.
It is short so hopefully, it should be soon-ish

Copy link
Collaborator

@thomas-lamiaux thomas-lamiaux left a comment

Choose a reason for hiding this comment

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

Thanks very much for writing it. It is a great addition on sth I know nothing of. Actually, I was not even aware of it.

I am reviewing it as an non-expert reviewers, so I tried to point out stuff that got me a bit confusing while reading.

Globally, I thought part 1 to 3 was a really good intro to the subject.

Concerning section 4, it depends on what you/we want to go with this.
As you mentioned, right now, it is more an explanation than a tutorial, because it just explains how it works and that it is.
I personally think it is a bit too bad, because at the end, you understand what are "bidirectional hints" but you have no idea when and how to use them.
That would be great if it were possible to modify the part 4 to help the user understand that.However, I have no idea how to do that, so I can't say much.

What do you think ? Note if no one has an example in mind, it can perfectly be merged like that, in which can we can create an issue to improve it latter.

@Lysxia
Copy link
Contributor Author

Lysxia commented Nov 4, 2024

As you mentioned, right now, it is more an explanation than a tutorial, because it just explains how it works and that it is.
I personally think it is a bit too bad, because at the end, you understand what are "bidirectional hints" but you have no idea when and how to use them.

I agree completely. As it is, this explanation works best for people who already have a little idea of what the feature does.

That would be great if it were possible to modify the part 4 to help the user understand that. However, I have no idea how to do that, so I can't say much.

I remember one common situation that calls for bidirectional hints is with dependently typed records. I can add a paragraph about that, maybe even lead with it, but it might not be a deep example that turns it into a tutorial.

@thomas-lamiaux
Copy link
Collaborator

You can also ask on zulip for examples, maybe someone has ideas.
Also I forgot to mention it but it should be said not to mess with such hints if you are a beginner.
I have never needed them, and I don't think too much people do ?


[[[
f ↑ forall (x : A), B x -> C x
a ↓ A C a ≡ T b ↓ B a
Copy link
Contributor

Choose a reason for hiding this comment

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

there is a subtlety here
after a ↓ A we know that f a : forall y : B a, C a
we could in principle check that y is not bound in C a before trying to unify C a and T
however in pretyping it is rare that we directly call "unify a and b", instead we usually want "coerce c : a to b"
this cannot be done without having a term c
(in fact it is not really right to write c ↓ T, it should really be something like "check input preterm c at input type T producing output term c'", similarly infer has an input preterm and output term and type)

so what we do is, regardless of if y is bound in the codomain:

  • generate a fresh evar ?y : B a
  • coerce f a ?y : C a (where C a is the result of substituting y := ?y inC a) to T (which first tries unifying C a to T and if that fails tries to find a coercion to insert)
    note that if y was bound in C a this could instantiate ?y
  • check b ↓ B a
  • unify ?y and b (this time it really is unification not coercion)
  • produce term f a b : C a (which is more faithful to what the user wrote than f a ?y if coercing to T instantiated ?y, but the C a is still from substituting ?y not b) and replay any coercions to T

@thiagofelicissimo
Copy link

Three comments from someone knowledgeable in bidirectional typing but not on bidirectionality hints:

  • It is a bit strange to present rule app-syn with a double application, and moreover you are also omitting the fact that some reduction is usually required after inferring the type of the head to expose the type former. Maybe what you could do is give the usual bidirectional rule for application and then say that your rule is the result of applying it twice to the term f a b.
  • In rule switch, I think you should replace conversion by subtyping.
  • In the Coq literature it is more usual to write t ▹ T for inference and t ◃ T for checking.

@MevenBertrand MevenBertrand self-requested a review December 20, 2024 13:18
Copy link
Contributor

@MevenBertrand MevenBertrand left a comment

Choose a reason for hiding this comment

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

Sorry for taking this long! All in all, the explanation is short but good, and does what it should, nice job 🚀

I only wonder whether it would be possible to have a slightly more "realistic" example, ie one where adding a bidirectionality hint actually helps in setting things up properly. Looking up "bidirectionality hints" on the zulip gives a handful of examples, maybe one of them can be distilled as an example 3?

@thomas-lamiaux
Copy link
Collaborator

@Lysxia Considering the comments, I suggest fixing them quickly, merging and opening an issue to add an example later on

@thomas-lamiaux
Copy link
Collaborator

@Lysxia
Copy link
Contributor Author

Lysxia commented Jan 30, 2025

Thanks all for the feedback!

I've integrated your suggestions (including starting with unary applications). I've added a mention of subtyping and coercions to make the reader aware of them, but without going into too much details to keep the rest of the explanation simple.

I'm also discussing the example earlier in the Bidirectionality Hints section to give more motivation.

@thomas-lamiaux thomas-lamiaux merged commit d2f66d8 into coq:main Jan 31, 2025
2 checks passed
@Lysxia Lysxia deleted the bidir-hints branch January 31, 2025 15:21
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.

5 participants