[GHC] #13324: Allow PartialTypeSignatures in the instance context of a standalone deriving declaration
#13324: Allow PartialTypeSignatures in the instance context of a standalone deriving declaration -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: feature | Status: new request | Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 (Type checker) | Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: None/Unknown Unknown/Multiple | Test Case: | Blocked By: Blocking: | Related Tickets: #10607 Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- Currently, if you try to use a wildcard anywhere in an instance context, it will fail immediately: {{{ $ ghci GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /home/rgscott/.ghci λ> instance _ => Show (Maybe a) <interactive>:1:10: error: Wildcard ‘_’ not allowed in an instance declaration for ‘Show’ }}} But there's one situation where we could lift this restriction: the context of a standalone, derived instance declaration. That is, something like this: {{{#!hs deriving instance _ => Show (Maybe a) }}} Why? Because GHC already has the machinery needed to infer what the context should be (see [http://git.haskell.org/ghc.git/blob/8a6b8c5fb96472d7c2e2cd1918950dd50f2fef71... this part] of `TcDerivInfer`), so if a user turned on `PartialTypeSignatures`, GHC could just fill in the wildcard with the inferred constraints. The implementation won't be //that// easy, however, since we'd also have to watch out for trickery such as: {{{#!hs deriving instance (C a, _) => C (T a b c) }}} I only mentioned putting wildcards in a derived instance //context//, because I think allowing the use of wildcards elsewhere in the instance head might be too difficult to deal with. I mean, how would you fill in this, for example? {{{#!hs instance (_ a) }}} This mini-feature has a very practical application: it would allow users to wield the flexibility of `StandaloneDeriving` without having to manually type in the instance context every time. That is, users could type in these instances: {{{#!hs deriving instance _ => Data (T a b c) deriving instance _ => Eq (T a b c) }}} Instead of their fully spelled-out, more laborious counterparts. This would be crucial for Template Haskell, as its ability to infer these contexts is quite limited (see #10607 for an example where this cropped up). Idle thought: could this be generalized to work for the instance context of //any// instance declaration (and not just derived ones)? From an outside perspective, it seems like typechecking other instances would require inferring constraints in a fashion quite similar to that of derived instances. But I am not at all familiar with that part of the typechecker, so I might be totally off here. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13324> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13324: Allow PartialTypeSignatures in the instance context of a standalone deriving declaration -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler (Type | Version: 8.0.1 checker) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #10607 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): We should make sure to watch out for these two corner cases: * Exotic constraints. Currently, trying to derive `Eq` like this: {{{#!hs newtype Foo f a = Foo (f (f a)) deriving Eq }}} Will be rejected with an error message saying: {{{ • No instance for (Eq (f (f a))) arising from the 'deriving' clause of a data type declaration Possible fix: use a standalone 'deriving instance' declaration, so you can specify the instance context yourself }}} That is, GHC will not put `Eq (f (f a))` into the set of inferred constraints because it is too "exotic". But presumably, we want a similar failure if the user instead typed this: {{{#!hs newtype Foo f a = Foo (f (f a)) deriving instance _ => Eq (Foo f a) }}} Since it's morally equivalent to just using a `deriving Eq` clause. * GADTs. GHC chooses not to even make an attempt if you try to stock- derive certain instances for GADTs with a `deriving` clause. For instance, this: {{{#!hs data T a where MkT :: T Int deriving Eq }}} is rejected with: {{{ • Can't make a derived instance of ‘Eq (T a)’: Constructor ‘MkT’ has existentials or constraints in its type Possible fix: use a standalone deriving declaration instead • In the data declaration for ‘T’ }}} So as a consequence, we should probably disallow this as well: {{{#!hs data T a where MkT :: T Int deriving instance _ => Eq (T a) }}} Notice that in both cases, the error message suggests trying a standalone deriving declaration! Obviously, we shouldn't do that if a user tries the equivalent, standalone approach with wildcards, so we should come up with a more appropriate error message for this scenario. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13324#comment:1> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13324: Allow PartialTypeSignatures in the instance context of a standalone deriving declaration -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler (Type | Version: 8.0.1 checker) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #10607 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj):
Since it's morally equivalent to just using a deriving Eq clause.
And it'll be implementationally the same as using `deriving Eq` too! So the same things will happen automatically. In the code, the `mtheta` variable will tbe `Nothing` rather than `Just`. Just allowing a wildcard on its own would be a good start. But we have code for doing the "subtraction" in cases like `(Eq a, _) => blah`, so it would not be too hard to support that too. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13324#comment:2> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13324: Allow PartialTypeSignatures in the instance context of a standalone deriving declaration -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler (Type | Version: 8.0.1 checker) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #10607 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by bgamari):
Instead of their fully spelled-out, more laborious counterparts. This would be crucial for Template Haskell, as its ability to infer these contexts is quite limited (see #10607 for an example where this cropped up).
It seems like for this to be useful we will want the ability to more precisely apply `PartialTypeSignatures` (in particular from splices) to ensure that users are forced to enable it for their entire module to avoid spurious errors. Is there a ticket for this yet? -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13324#comment:3> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13324: Allow PartialTypeSignatures in the instance context of a standalone deriving declaration -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler (Type | Version: 8.0.1 checker) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #10607 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): bgamari, yes, I believe #8510 is what you are looking for. I don't think that implementing this feature would be that difficult, either, since: 1. We already have a `Extension` datatype for representing all GHC extensions 2. The GHC API already has `setXOptM`/`unsetXOptM` for enabling/disabling `Extensions` within the scope of some computation So I think we'd just need a Template Haskell function `qWithExtensions :: Quasi m => [OnOff Extension] -> m a -> m a` that enabled/disables whatever the user provides. Then libraries like `deriveTopDown` could just use `qWithExtensions [On PartialTypeSignatures]` to wrap any splices that contain wildcard types. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13324#comment:4> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13324: Allow PartialTypeSignatures in the instance context of a standalone deriving declaration -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler (Type | Version: 8.0.1 checker) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #10607 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): Do you also, as #13415 implies, want the non-`deriving` case to work? {{{ instance _ => C (T a) where op x = ... bop y = ... }}} This would be more ambitious, because you'd have to infer the constraints for the arbitrary user-written code in "...", and `TcInstDcls` isn't set up to do that. Remember that two instance declarations might both need each other. That's why there's a fixpoint in the deriving code. I think it'd be a lot easier to handle the deriving case than the general case. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13324#comment:5> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13324: Allow PartialTypeSignatures in the instance context of a standalone deriving declaration -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler (Type | Version: 8.0.1 checker) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #10607 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): Replying to [comment:5 simonpj]:
Do you also, as #13415 implies, want the non-`deriving` case to work?
Indeed, I think that if I can figure out how to make it work for `deriving`, I don't think inferring constraints for arbitrary instances would be that fundamentally different in operation. Granted, I don't think I'm going to knock out both at the same time. Baby steps and all. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13324#comment:6> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13324: Allow PartialTypeSignatures in the instance context of a standalone deriving declaration -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler (Type | Version: 8.0.1 checker) | Resolution: | Keywords: deriving Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #10607 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * keywords: => deriving -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13324#comment:7> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13324: Allow PartialTypeSignatures in the instance context of a standalone deriving declaration -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler (Type | Version: 8.0.1 checker) | Resolution: | Keywords: deriving Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #10607 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by Iceland_jack): * cc: Iceland_jack (added) -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13324#comment:8> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13324: Allow PartialTypeSignatures in the instance context of a standalone deriving declaration -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: feature request | Status: patch Priority: normal | Milestone: Component: Compiler (Type | Version: 8.0.1 checker) | Resolution: | Keywords: deriving Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #10607 | Differential Rev(s): Phab:D4383 Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * status: new => patch * differential: => Phab:D4383 -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13324#comment:9> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13324: Allow PartialTypeSignatures in the instance context of a standalone deriving declaration -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: feature request | Status: patch Priority: normal | Milestone: Component: Compiler (Type | Version: 8.0.1 checker) | Resolution: | Keywords: deriving Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #10607 | Differential Rev(s): Phab:D4383 Wiki Page: | -------------------------------------+------------------------------------- Comment (by Simon Peyton Jones <simonpj@…>): In [changeset:"1c062b794bf71a329f65813ce7b72fe2bd3935f0/ghc" 1c062b79/ghc]: {{{ #!CommitTicketReference repository="ghc" revision="1c062b794bf71a329f65813ce7b72fe2bd3935f0" Simplify rnLHsInstType This patch is preparatory for the main fix for Trac #13324 Here, we simplify rnLHsInstType so that it does not try to figure out the class name. This turns out to have a good (rather than bad) effect on error messages, and it prepares the way for the main event. Plus, less code! }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13324#comment:10> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13324: Allow PartialTypeSignatures in the instance context of a standalone deriving declaration -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: feature request | Status: patch Priority: normal | Milestone: Component: Compiler (Type | Version: 8.0.1 checker) | Resolution: | Keywords: deriving Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #10607 | Differential Rev(s): Phab:D4383 Wiki Page: | -------------------------------------+------------------------------------- Comment (by Ryan Scott <ryan.gl.scott@…>): In [changeset:"affdea82bb70e5a912b679a169c6e9a230e4c93e/ghc" affdea82/ghc]: {{{ #!CommitTicketReference repository="ghc" revision="affdea82bb70e5a912b679a169c6e9a230e4c93e" Allow PartialTypeSignatures in standalone deriving contexts Summary: At its core, this patch is a simple tweak that allows a user to write: ```lang=haskell deriving instance _ => Eq (Foo a) ``` Which is functionally equivalent to: ```lang=haskell data Foo a = ... deriving Eq ``` But with the added flexibility that `StandaloneDeriving` gives you (namely, the ability to use it anywhere, not just in the same module that `Foo` was declared in). This fixes #13324, and should hopefully address a use case brought up in #10607. Currently, only the use of a single, extra-constraints wildcard is permitted in a standalone deriving declaration. Any other wildcard is rejected, so things like `deriving instance (Eq a, _) => Eq (Foo a)` are currently forbidden. There are quite a few knock-on changes brought on by this change: * The `HsSyn` type used to represent standalone-derived instances was previously `LHsSigType`, which isn't sufficient to hold wildcard types. This needed to be changed to `LHsSigWcType` as a result. * Previously, `DerivContext` was a simple type synonym for `Maybe ThetaType`, under the assumption that you'd only ever be in the `Nothing` case if you were in a `deriving` clause. After this patch, that assumption no longer holds true, as you can also be in this situation with standalone deriving when an extra-constraints wildcard is used. As a result, I changed `DerivContext` to be a proper datatype that reflects the new wrinkle that this patch adds, and plumbed this through the relevant parts of `TcDeriv` and friends. * Relatedly, the error-reporting machinery in `TcErrors` also assumed that if you have any unsolved constraints in a derived instance, then you should be able to fix it by switching over to standalone deriving. This was always sound advice before, but with this new feature, it's possible to have unsolved constraints even when you're standalone-deriving something! To rectify this, I tweaked some constructors of `CtOrigin` a bit to reflect this new subtlety. This requires updating the Haddock submodule. See my fork at https://github.com/RyanGlScott/haddock/commit/067d52fd4be15a1842cbb05f42d9d4... Test Plan: ./validate Reviewers: simonpj, goldfire, bgamari Reviewed By: simonpj Subscribers: goldfire, rwbarton, thomie, mpickering, carter GHC Trac Issues: #13324 Differential Revision: https://phabricator.haskell.org/D4383 }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13324#comment:11> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13324: Allow PartialTypeSignatures in the instance context of a standalone deriving declaration -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: feature request | Status: closed Priority: normal | Milestone: 8.6.1 Component: Compiler (Type | Version: 8.0.1 checker) | Resolution: fixed | Keywords: deriving Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: partial- | sigs/should_compile/T13324_compile, | partial- | sigs/should_fail/T13324_fail1, | partial- | sigs/should_fail/T13324_fail2 Blocked By: | Blocking: Related Tickets: #10607 | Differential Rev(s): Phab:D4383 Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * status: patch => closed * testcase: => partial-sigs/should_compile/T13324_compile, partial- sigs/should_fail/T13324_fail1, partial-sigs/should_fail/T13324_fail2 * resolution: => fixed * milestone: => 8.6.1 -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13324#comment:12> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
participants (1)
-
GHC