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
Deprecated instances #575
Deprecated instances #575
Conversation
Thank you @int-index for writing this up! It's somewhat telling that the only nitpick I can find is the deprecation message 😅 in the example. I think
would be better than
as the second one assumes someone to knows where deepseq is hosted, and how to find issue #16 from there. (the other is that I'm just lazy and like clicking things in terminal 😱). |
I leave the exact wording to |
Fair, I was more concerned about this setting a precedence, where the next person needing this Deprecation ends up reading the proposal, and then copies the format ;-) Not specifically about this deepseq one. After all it's just an example. |
Another ignominious example: |
Strong agree that we need this. But I wonder whether we should do this via #454. Deprecating instances that way would not invoke many of the objections to that proposal, such as decreased performance. |
Thanks for writing this up! As the author of #454, I think this proposal is a good alternative to that one. It's simpler and gets most of the remaining value. In particular, I believe this should work: type WarnInteger :: Type -> Constraint
type family WarnInteger a where
WarnInteger Integer = UnboundedMemoryWarning
WarnInteger a = ()
class UnboundedMemoryWarning
instance UnboundedMemoryWarning {-# WARNING [x-decode-integer] "Integer may require unbounded memory!" #-} It isn't possible to use type information to construct the text of the warning message or category, unlike #454, but we don't have any really compelling need for that AFAIK. In Section 3.1, there is a very minor interaction with #541 which changed the syntax of |
@tomjaguarpaw, just to make sure I understand what you are saying here, you suggest to go via #454 instead, as for this specific case of instance deprecation, the objections to #454 with respect to performance do not apply? I like the idea in #454, but it appears to me that it would introduce completely separate syntax (however potentially more powerful), for deprecations. At which point I wonder if #454 should just subsume all current applications of deprecation pragmas? It also seems more heavyweight than this. So maybe we can go with this lightweight proposal, and consider improving the general deprecation pragmas with a more generalised solution in #454 (though @adamgundry appears to think that this might not be necessary?). That might then requires us to be able to deprecate deprecation pragmas 🙈 |
I see the intent, but why not use the exact same mechanism as
where We don't really want two very similar features with entirely different designs, do we? |
Am I right in assuming the Unsatisfiable proposal #433 has not been implemented yet? Maybe I'm misreading ghc/ghc#20835. I've tried to play with this as it indeed looks like a good solution to what we want (except for the |
To be clear, I think this proposal is essential and urgent, and I'm not too bothered by the UI that we choose to expose for it. To bikeshed, I like the idea of features implemented "in-band" at the language level as alternatives to "out-of-band" ad hoc syntax. That's why I liked #454. I recall there were some objections to it regarding the cost of picking up a dictionary at run time. Since this proposal is about classes anyway, that objection wouldn't apply. However, if #454's author Adam prefers this proposal, perhaps I'm off base. Yet Simon seems to be thinking the same as me. Anyway, I don't mind. Let's get this done. It's essential. |
@angerman Indeed #433 has not yet been implemented. (I'd love someone to pick it up!) @simonpj You're essentially suggesting #454. 😄 The pragma-based approach suggested here is closer to the existing deprecation/warning pragmas; the class-based approach is closer to Ultimately I think either approach is reasonable, and I'm happy with whichever approach ends up being taken. |
I fully agree with @tomjaguarpaw, and even if this is just a stop-gap measure to improve the overall ecosystem's ability to properly deprecate instance methods (and it follows the exact same pattern we have for existing deprecations instead of a different syntax). This seems even fairly lightweight? Maybe we can make a case if it turns out to be as lightweight as assumed, to be in 9.6.x to assist with deprecation (and migration) needs. The ticket that spawned this has started in 2016. Edit: clarification, I did not mean 9.6.2. I should have been more explicit with that, instead of writing 9.6.x I was more thinking of a back port into 9.6.4 or some subsequent release, to specifically allow for proper deprecation, and thus make migration and compat with subsequent release (9.8, ...) easier. The whole motivation behind this is to have the ability to inform downstream consumers of deprecations, so they can plan ahead. |
No. simply no. People have already started on working on compat for GHC-9.6. We have been "sold" a six month GHC release cadence so we don't need to hastily try to get features in, for the price of more GHCs to test-with / migrate to etc. IMO the promise is still to be delivered, but let's not make it impossible resulting in the worst of both: unpredicatable yet frequent release cadence. |
Three things:
The 9.6.x suggestion was exclusively to help packages like |
It will impact GHC folks to deliver GHC-9.6 on schedule.
Famous last words. |
The feature window for 9.6 is closed, and this proposal is not a bugfix, it's a new user-facing feature. Not only that, it's a proposal for a feature: not accepted yet, not implemented yet. We are not in a position to discuss its addition to 9.6 |
OK fine. My point is simply this: we should either
I'm uncomfortable about doing both. I hear a note of urgency, but it's a bad idea to put in a feature (pragmas) that we are going to deprecated in the forseeable future. Let's just decide what we want and do that. |
@simonpj I disagree.
|
Interesting. I didn't know that. (Side issue, but I'd be interested in an example.) It's true that one affects semantics and the other does not, but that doesn't mean that their designs must look so different. All the motivations for Unsatisfiable apply equally to Deprecated: see this section |
That is a proposal about custom type warnings constraint. Not about Unsatisfiable. |
But @simonpj is right if #454 is accepted and implemented, it subsumes most the motivation for this proposal. At least the trigger motivation point (the |
I think it means exactly that. When I see a constraint, I know that it will be desugared into a dictionary and it will be carried around at runtime unless specialized, and it may or may not be solved. This is something I would expect from And I want none of that when I reason about deprecations and warnings, which should be strictly limited to messages that GHC emits. The pragma syntax is a strong indicator of that. And it's not a new pragma, I'm just extending the existing practice, for which I cited over 3 thousand uses on Hackage. Our users, library authors, know how to use deprecation pragmas. Let them use the familiar feature in instances. |
Are you seriously suggesting that |
As additional motivation, see my comment here: haskell/core-libraries-committee#86 (comment) The context is that we want to restrict the type of unzip :: UnzipDeprecation f => Functor f => f (a,b) -> (f a, f b)
unzip xs = (fst <$> xs, snd <$> xs)
class UnzipDeprecation f
instance UnzipDeprecation f {-# DEPRECATED "..." #-}
instance {-# OVERLAPPING #-} UnzipDeprecation NonEmpty |
instance {-# INCOHERENT #-} UnzipDeprecation NonEmpty seems to compile fine. Is there a problem with that? I agree that uses of overlapping instances are rarely good, but this case, where we're not actually trying to pick up a type class implementation, seems fine. |
@int-index It looks like the proposal is ready to be submitted to the committee, isn't it? We are interested in this feature and you may add to the implementation plan that @barci2 will implement it as part of his internship at IOG. |
@nomeata Let's submit this. |
I'm recommending acceptance of this proposal. All concerns have been sufficiently considered as far as I can see. |
I'm content to accept this. One niggle:
Why put the
Now I can put them in any order. |
I agree with @simonpj, it would be better if the pragmas could be placed in any order, although I'd rather do it something like this: |
It's postfix for consistency with modules where we write Perhaps consistency is not important here, or maybe we could allow the pragmas to come both in prefix and postfix positions. I only tried to follow the established precedent. Do we have a good reason to deviate from it? |
The good reason is that the other pragmas are prefix. I have no objection to making all of them either prefix or postfix or both; the only thing I dilike is making one prefix and the other postfix. I'm only one person. I'd love opinions from others . |
Well now deprecated exports are prefix, so you can make an argument the other way around with those as well |
@int-index what's the consensus then, do we do it like with export deprecation or like with module deprecation? |
Aha, that is an excellent point. Easily fixed, but it would be odd not to make it consistent. |
I've asked Eric about potential solutions to his concerns in https://mail.haskell.org/pipermail/ghc-steering-committee/2023-May/003240.html; @int-index what's your stance on including standalone deriving and changes to the placement of pragmas in the proposal? |
On the syntax I have an opinion (these are easy to come by, of course, and hard to sort). My brain fully expects the |
While I think my brain seems to work similar to yours, I value consistency more. It makes it much less surprising to find it one way here and another there. Maybe prefix deprecations should be a separate proposal? Which would then also need deprecation warnings ("move your deprecation annotation to the front please"). Lumping moving deprecations into prefix position everywhere in this proposal feel a lot like scope creep. My stance therefore is:
Optionally have a separate proposal for prefix deprecations. |
I updated the proposal based on the recent discussion.
As to permitting instance pragmas in arbitrary order (i.e. swapping @angerman I'd like to resubmit the updated proposal to the committee. |
@nomeata this has now been implemented in master and will probably land in 9.10. |
The proposal has been accepted; the following discussion is mostly of historic interest.
GHC allows to deprecate modules, functions, data constructors, type constructors, but not instances. The lack of support for deprecation of instances makes it impossible to remove them gracefully, with an advance warning to the users. We propose to allow
{-# WARNING ... #-}
and{-# DEPRECATED ... #-}
pragmas on instances to correct this.Rendered