FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Support deriving via by kl0tl · Pull Request #3824 · purescript/purescript · GitHub

Support deriving via - #3824

Open
kl0tl wants to merge 1 commit into
purescript:masterfrom
kl0tl:deriving-via
Open

Support deriving via#3824
kl0tl wants to merge 1 commit into
purescript:masterfrom
kl0tl:deriving-via

Conversation

kl0tl commented Mar 27, 2020
edited
Loading

Copy link
Copy Markdown
Member

It looks like it works but there’s a few things I need help with:

  • I had to add cases for ParensInType in various places. This constructor doesn’t usually seem to be present in types but it is in via types. Is it supposed to be somehow removed?
  • This is perhaps related to the previous point but the error messages I added contain unfortunate line breaks after prettified via types.
  • I would like to throw a more helpful error than NoInstanceFound when the kinds of the via type and of the instance head last type don’t unify. I tried to elaborate those kinds but elaborating the kind of an application whose first parameter has a polymorphic kind fails.

For instance Data.Functor.Compose.Compose has such a polymorphic kind:

newtype Compose ::  k1 k2. (k1 -> Type) -> (k2 -> k1) -> k2 -> Type

meaning that elaborating the kind of Compose (Either e) Maybe fails when elaborating the application of Compose to Either e. Should I approach this differently?

Also I took the liberty to rename MissingNewtypeSuperclassInstance to MissingSuperclassInstance since this error is thrown for both newtype and via instances, removed the mention of derived superclass instance from its message (since any instance actually qualify) and replaced the InvalidNewtypeInstance error thrown when trying to derive a newtype instance for a nullary type class by a new CannotDeriveNullaryTypeClassInstance error (which is also thrown for via instances).

Close #3302.

Copy link
Copy Markdown
Contributor

I had to had cases for ParensInType in various places. This constructor doesn’t usually seem to be present in types but it is in via types. Is it supposed to be somehow removed?

ParensInType is removed as part of operator desugaring (removeParens). You are probably missing a case when traversing types for the deriving via declaration.

kl0tl commented Mar 28, 2020

Copy link
Copy Markdown
Member Author

Oh thank you, I added the guilty case 🙇 Also I fixed my error messages and moved most of the deriving via checks into the type checker because I was duplicating a lot of work to infer kinds.

'then' { SourceToken _ (TokLowerName [] "then") }
'true' { SourceToken _ (TokLowerName [] "true") }
'type' { SourceToken _ (TokLowerName [] "type") }
'via' { SourceToken _ (TokLowerName [] "via") }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Since this is a contextual keyword, you will need to make sure to add it ident, qualIdent, and label.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Good catch! Sorry about that, I added a few test cases to cover this.

kl0tl commented Mar 29, 2020

Copy link
Copy Markdown
Member Author

I managed to ensure the via kind unifies with the kind of the type for which the instance is derived! Elaborating the kinds didn’t work but inferring them after binding all free variables to fresh kinds (like it is done when checking instances declarations) does 🎉

, solverDeferErrors = False
}
void . flip runStateT M.empty . runWriterT $
entails solverOptions constraint M.empty []

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Does this throw away the unsolved constraints?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Oh, but that's fine because of the current SolverOptions, so the solver won't emit unsolved constraints and instead just fail, right? I guess that means we can't write something like

data T

derive via (...) instance blah :: Coercible X Y => Cls T

i.e. defer Coercible constraints in the instance head, but that's not a big loss, and maybe something that can be solved later?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

The solver indeed fails when typechecking the instance declaration if the generated constraint can’t be solved but it doesn’t try to solve the instance context, so you can write such instance.

gSimple (MissingNewtypeSuperclassInstance cl1 cl2 ts) = MissingNewtypeSuperclassInstance cl1 cl2 <$> traverse f ts
gSimple (UnverifiableSuperclassInstance cl1 cl2 ts) = UnverifiableSuperclassInstance cl1 cl2 <$> traverse f ts
gSimple (InvalidViaType cl ts viaTy) = InvalidViaType cl <$> traverse f ts <*> f viaTy
gSimple (InvalidViaKind cl ts viaTy viaKind expectedKind) = InvalidViaKind cl <$> traverse f ts <*> f viaTy <*> f viaKind <*> f expectedKind

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Should f be called on kinds here? There’s no case for the KindsDoNotUnify error for instance so maybe it shouldn’t 🤔

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

If there are cases that are missing it's probably an oversight.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

The following SimpleErrorMessage constructors hold SourceTypes but aren’t matched:

  • InfiniteKind
  • EscapedSkolem
  • KindsDoNotUnify
  • MissingClassMember
  • UserDefinedWarning
  • QuantificationCheckFailureInType
  • UnsupportedTypeInKind

Should I add cases for them in this PR? Matching every constructor explicitly would be verbose but could help to prevent this in the future.

Copy link
Copy Markdown
Contributor

One thing to consider with this syntax is #1120. If we allowed forall for instances, the via clause would be outside of the binder. Should we discuss making via a proper reserved word and put it at the end of the instance? Obviously that ticket isn't a done deal, but I think it's something other maintainers are keen on, so some bike-shedding might be appropriate.

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
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.

Support deriving via

3 participants


Back | FazBrowse Home | New Git URL