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

feat: display and edit kinds on foralls #1120

Merged
merged 24 commits into from
Sep 19, 2023
Merged

Conversation

brprice
Copy link
Contributor

@brprice brprice commented Aug 17, 2023

Notes for reviewers: Sorry the PR is so large; I think most of it is fairly mechanical refactors and I have tried to split those into separate commits where I can

@brprice brprice linked an issue Aug 17, 2023 that may be closed by this pull request
@brprice brprice force-pushed the brprice/forall-kind-edit branch 2 times, most recently from 985a2cc to 7cfe2e4 Compare September 7, 2023 14:06
@brprice brprice changed the title WIP: display and edit kinds on foralls feat: display and edit kinds on foralls Sep 7, 2023
primer/src/Primer/TypeDef.hs Outdated Show resolved Hide resolved
primer/src/Primer/TypeDef.hs Outdated Show resolved Hide resolved
@brprice brprice marked this pull request as ready for review September 7, 2023 14:13
@brprice brprice requested a review from a team September 7, 2023 14:13
Copy link
Contributor

@georgefst georgefst left a comment

Choose a reason for hiding this comment

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

Great stuff. Thank you for taking on this work!

@@ -25,7 +26,7 @@ tasty_focus_unfocus_roundtrip = property $ do
tasty_focusOn_unfocus_roundtrip :: Property
tasty_focusOn_unfocus_roundtrip = property $ do
e <- forAll $ evalExprGen 0 genExpr
i <- forAll $ Gen.element $ idsIn e
i <- forAll $ Gen.element $ e ^.. exprIDs
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems a stretch to call this a refactor: given that (^.. exprIDs) has different behaviour to idsIn and thus the test is more general.

primer-api/src/Primer/API.hs Outdated Show resolved Hide resolved
@@ -167,7 +167,8 @@ data NoInputAction
| DeleteTypeParam
| MakeKType
| MakeKFun
| DeleteKind
| -- TODO: RaiseKind?
Copy link
Contributor

@georgefst georgefst Sep 11, 2023

Choose a reason for hiding this comment

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

Yes, we probably should have a "raise kind" action. Though I don't mind whether that's in a separate PR.

Copy link
Contributor

@georgefst georgefst Sep 12, 2023

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is now tracked in #1145

-- TODO/REVIEW: when testing editable-forall-kinds, I noticed that we would not elide the hole in
-- foo : ∀a:*.? ; foo = {? ? : ∀a:*.? ?}
-- but this is odd -- the annotations are identical (so not acting as a typechange)!
-- (also, note that we keep hole-wrapped-holey-anns around because of the below even when we would accept the non-wrapped version (indeed, have an action that will do that!)
Copy link
Contributor

@georgefst georgefst Sep 11, 2023

Choose a reason for hiding this comment

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

This is odd. Do you have any inkling as to why it occurs?

Copy link
Contributor Author

@brprice brprice Sep 19, 2023

Choose a reason for hiding this comment

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

Yes. This is actually #7. The current design is

  • When synthesising "never elide holes", i.e. do not automatically do {? e ?} ~> e when we have no information about the context. NB: if we did elide, it could change the synthesised type and force new holes to appear elsewhere in the program.
  • When checking T ∋ {? e ?} we attempt to elide the hole if that would be type-correct by the transformations
    • if checking nested holes T ∋ {? {? e ?} ?}, drop one layer and recurse T ∋ {? e ?}
    • if have an annotation in a hole (this is the case referred to in this comment) T ∋ {? s : S ?}, we
      • drop a hole-and-trivial-annotation, if it is still type-correct {? s : ? ?} changes to s, if we have T ∋ s
      • never touch holes-and-incomplete-annotations (this is our current example), i.e. if there is a type hole in the annotation S, as (quoting Typecheck.hs)

        Don't want to, e.g., remove {? λx.x : ? ?} to get λx.x : ? Since holey annotations behave like non-empty holes, we will not elide non-empty holes if they have a holey annotation. (This is needed for idempotency, since we return non-empty holes with holey-annotated contents in the case a construction cannot typecheck, e.g. Bool ∋ λx.t returns {? λx.t : ? ?}

      • otherwise fall through to the "have a hole, and don't care about the contents" case
    • if none of the above are true, we have a hole and don't care about the contents, in which case we elide the hole leaving e as long as that is type-correct

(NB: above, where I say "elide...as long as that is type correct" and similar, by "type correct" I actually mean "smart holes accepts the term and does not create a hole at top level", i.e. it could result in "pushing down the hole")

(If you think this seems somewhat convoluted, then I agree: this logic should be revisited!)

Copy link
Member

Choose a reason for hiding this comment

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

Can you add a comment in the code here with a link to the parent post, and also a link to #7, please?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can you add a comment in the code here with a link to the parent post, and also a link to #7, please?

Will do, but in a separate PR since it is orthogonal to the current changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can you add a comment in the code here with a link to the parent post, and also a link to #7, please?

Will do, but in a separate PR since it is orthogonal to the current changes.

See #1147

primer/src/Primer/TypeDef.hs Outdated Show resolved Hide resolved
Signed-off-by: Ben Price <ben@hackworthltd.com>
Signed-off-by: Ben Price <ben@hackworthltd.com>
Signed-off-by: Ben Price <ben@hackworthltd.com>
Signed-off-by: Ben Price <ben@hackworthltd.com>
Before this commit, it used `idsIn` which only gave IDs of expression
nodes, and not type nodes within type annotations or applications. Thus
these tests are now slightly stronger.

Signed-off-by: Ben Price <ben@hackworthltd.com>
Signed-off-by: Ben Price <ben@hackworthltd.com>
Signed-off-by: Ben Price <ben@hackworthltd.com>
This is usually instantiated to `()`, matching the previous hardcoded
choice. There are intended to be no functional changes in this commit,
it is simply setup for adding IDs to kinds in foralls (and thus to enable
actions in those positions).

(Note that there are a couple of TODOs added in comments which will be
addressed in a subsequent commit.)

Signed-off-by: Ben Price <ben@hackworthltd.com>
This requires reworking `forgetTypeDefMetadata` and `generateTypeDefIDs`,
where we can use generic optics instead of the current traversals.

We do this in preparation for adding metadata to kinds in types. This
will include kinds within fields of constructors. When that happens, the
same type parameter will control the metadata in two separate fields of
ASTTypeDef, meaning the old type-changing lens-style definitions would
become very awkward.

Signed-off-by: Ben Price <ben@hackworthltd.com>
We now have a general "nested zipper" definition, which will be used to
focus on kinds-inside-types{,-inside-exprs} later.

Signed-off-by: Ben Price <ben@hackworthltd.com>
We define a helper datatype, rather than nesting `Either`s. This gives
much better names of constructors, and makes it easier to extend when
we shortly enable focusing on kinds.

Signed-off-by: Ben Price <ben@hackworthltd.com>
We add a `Void` field to such selections so that it is clear we don't
yet create them, and it is easy to stub out some codepaths that do not
yet make sense (mostly due to kinds not having IDs yet).

Note that `findTypeOrKind` (and friends) only work for the kind parameter
being `()`, and consequently do not actually focus on kinds (they have
no IDs).

Signed-off-by: Ben Price <ben@hackworthltd.com>
This will be reused shortly, when we enable actions on kinds in foralls.

Signed-off-by: Ben Price <ben@hackworthltd.com>
This is setup for kinds being selectable. (Currently we actually return
a second summand of `(KindTZ, Void)`, since we never actually focus on
kinds. This `Void` will be dropped shortly.)

Signed-off-by: Ben Price <ben@hackworthltd.com>
We also remove `findType` usage from API, in favor of `findTypeOrKind`
(currently these are equivalent, but the latter more clearly expresses
the plan to enable kinds-in-foralls to be selectable.

Note that the refactoring is slightly stricter with throwing a
`NodeIDNotFound` error.

Signed-off-by: Ben Price <ben@hackworthltd.com>
This is a trivial-but-invasive refactoring to set up for adding IDs
to kinds-in-foralls. The new definitions khole', ktype', kfun' are
temporary and will be collapsed into their non-primed versions when we
have added IDs.

Signed-off-by: Ben Price <ben@hackworthltd.com>
This removes our usage of `Void`, and fills out those codepaths that
were stubbed out due to lacking ids.

Note that this commit introduces some TODOs which will be addressed in
a subsequent commit.

Signed-off-by: Ben Price <ben@hackworthltd.com>
Signed-off-by: Ben Price <ben@hackworthltd.com>
Now that we have unique IDs on kinds, this is possible whilst giving
unique `nodeId`s in the api's result.

BREAKING CHANGE: this affects our API. Our advertised OpenAPI interface
remains the same, but the data we return will differ.

Signed-off-by: Ben Price <ben@hackworthltd.com>
This does not change our API, we simply accept some actions in positions
that we previously did not.

Signed-off-by: Ben Price <ben@hackworthltd.com>
We replace the last usage and delete the function. There is no need
to keep this footgun around (it is too easy to forget that it doesn't
select kinds).

Signed-off-by: Ben Price <ben@hackworthltd.com>
Signed-off-by: Ben Price <ben@hackworthltd.com>
Signed-off-by: Ben Price <ben@hackworthltd.com>
This is consistent with other actions.

BREAKING CHANGE: this changes the richly-typed API

Signed-off-by: Ben Price <ben@hackworthltd.com>
@brprice brprice added this pull request to the merge queue Sep 19, 2023
Merged via the queue into main with commit 2bf2349 Sep 19, 2023
2 checks passed
@brprice brprice deleted the brprice/forall-kind-edit branch September 19, 2023 14:09
@brprice brprice mentioned this pull request Nov 8, 2023
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.

FR: Provide API for displaying and editing kinds on foralls
3 participants