GHC Proposal #601 proposes a lifecycle for Haskell language extensions and an associated system of compiler warnings. The lifecycle categorizes language extensions as being one of the following:
An experimental extension, subject to rapid evolution (e.g. LinearTypes)
A mature extension, to which changes are not expected (e.g. DeriveFunctor)
A deprecated extension, which will be removed from an imminent GHC release
A legacy extension, which is generally considered to be a design dead-end but that is not scheduled for removal (e.g. NPlusKPatterns)
The compiler warnings would (configurably) warn about the use of experimental, legacy, or deprecated extensions.
The Haskell Foundationâs Stability Working Group thinks that this can solve a real need: teams of Haskell developers will be able to more easily understand the status of extensions and express machine-checked policies for CI. Furthermore, if an extension changes categories (e.g. moving from âexperimentalâ to âdeprecatedâ), the new warnings on a compiler update will be a good reminder to check the release notes and see what needs to be done.
The GHC Steering Committee is currently evaluating the proposal. They are interested in feedback from industrial teams - if youâre using Haskell at work, please chime in on the thread, even if your comment is just âSounds helpfulâ or âNot relevant to usâ (although substantive comments are of course also welcome).
The Semigroup change wasnât a language extension, and I donât think Monad Fail was (I guess it impinged somehow on desugaring but I donât think it was an extension at any point).
Mature extensions are considered to be finished and are not expected to undergo regular changes. These features can be used without worry of unexpected changes, and they are not known to contain serious design or implementation deficiencies. Any breaking change to a mature extension will be announced well in advance of the change being made, with a migration path provided if possible.
As @tomjaguarpaw indicates, neither of those changes were to extensions, so they would not have been impacted by this proposal.
That is the happy path, which in the proposal is experimental â mature. But deprecated & legacy are for sad paths, namely how to scheduling sunsets of some extensions.
From how I read, âmatureâ ones have high assurance for you in that matter. âlegacyâ ones may also work, but itâs also a warning to you that you might want to move away from it.
hmm, thatâs probably the intention of extension sets: Haskell 98/2010, GHC 2021?
To be clearer, what I meant was being legacy or deprecated is a tag associated with the path, and not the path itself. Once it hits mature and users start using it, there should not be any breaking changes even if it goes into legacy or deprecated, which means that these apis should remain there for some defined X versions from the warning until its confirmed that nobody uses it at all (and since this is hard to confirm, in practice this means nothing is removed once it hits mature).
This level of guarantee allows industry users to use what they want safely without fear of needing to dedicate time to refactor something because it has become deprecated. The industry can trust mature extensions are well designed with long lasting semantics.
There was an extension called MonadFailDesugaring which was added in 8.0.1, enabled by default in 8.6.1 and removed in 9.0.1 (I think, canât find it in the release notes). I suppose it could be considered mature in GHC 8.6.1?
Maybe we could distinguish âsupersededâ (when there is a new extension that includes the same functionality and there is a clear migration path, like the case of MonadFailDesugaring) and âdeprecatedâ (when the idea is flawed and/or abandoned).
Not sure this helps anyone though.
(I only skimmed the proposal, apologies if this has already been considered or discussed)
My company uses Haskell to deploy web services. I think we find this useful for a couple of reasons:
we would default to only allowing mature extensions, to avoid future maintenance work. Ideally this could be changed in a per-file and per-package basis, eg if we really wanted to use LinearTypes in one module.
We would find where we were using deprecated extensions before they were removed, enabling gradual migration away from them.
I am not sure we want to promise that, and the proposal actually says
Any breaking change to a mature extension will be announced well in advance of the change being made, with a migration path provided if possible.
If we could predict the future, then maybe we could make an absolute statement, but in light of more information, I hope we can still make any change â with due process. Thatâs the point of Deprecated, isnât it?
I am not sure we want to promise that, and the proposal actually says
If this cannot be promised for certain LTS major or minor versions, as noted above by @maxigit then marking something as âmatureâ has no difference from being âexperimentalâ. âHigh assuranceâ isnât something that can be quantified or planned for.
If we could predict the future, then maybe we could make an absolute statement, but in light of more information, I hope we can still make any change â with due process. Thatâs the point of Deprecated, isnât it?
Languages suitable for wider enterprise adoption often have long-lasting semantics, especially for LTS versions (up to X amount of years), and I believe we can all learn something from the Python 2->3 fiasco. This is not about âpredicting the futureâ, this is about committing to stability for a certain amount of time that can be factored into planning and reducing the risk of using Haskell in production.
Today, some extensions are known to be basically âfinishedâ, and considered unlikely to ever change. Others are considered to be unfinished, subject to more or less rapid iteration as the contact with real users casts light on the design. It is highly unlikely that one of these âfinishedâ extensions would be removed or drastically changed, certainly not without a long deprecation cycle. On the other hand, rapid iteration from release to release of a new feature is normal and expected.
How are users to know which is which? This proposal seeks to provide a means by which it can be communicated, and by which changes to that communication can be checked in CI.
I totally get that it doesnât solve every problem - there are lots of things we can do to improve things! Do you think that this makes things better, though?
RankNTypes was infamously changed recently which broke a whole lot of code and spawned the new DeepSubsumption extension that undoes the change. Also, ExistentialQuantification has changed and will probably soon change again, see the other thread (that is a rather trivial change, but it could break code).
GHC2021 has become the default. Removing old extensions just breaks existing code for little reason. I guess you could argue it would improve discoverability of the remaining extensions, but that doesnât weigh up against the breakage it would cause; the categorisation proposed here would be a better way to improve discoverability in my opinion.
I agree. I hope we will get to the point where the latest GHC20xx is perceived not as a set of extensions, but as a wholesome language edition, and the documentation structure hopefully will support that.
The old editions (Haskell2010, GHC2021, all the various extensions to these base lines) may still be supported to not break code lying around untouched. But hopefully developers who write fresh code, or who keep following the GHC20xx language editions with their actively maintained code, will no long have to think of so many extensions as features.
DatatypeContexts was removed by GHC2010 â chiefly so that we could experiment with bringing back the syntax but with more helpful semantics.
The current extensions around DuplicateRecordFields/Disambiguation and friends are regarded as experimental and liable to change. (That is, some of the implementation detail might change, not the proposed syntax: the implementation has run into some fishhooks.) And amongst the âfriendsâ, NoFieldSelectors takes away a H98 feature.
Not true looking back over ~25 years; but I agree GHC has been getting more timid over the past (say) 5 years. Since DatatypeContexts is still âon the booksâ, thereâs a risk someoneâs still using it, so can we actually introduce something more helpful under that name?
Yeah. Iâm pretty sure Davidâs o.p. wasnât aimed at me (as a hobby user), so Iâve kept off this thread.
Thatâs right - this proposal was written specifically to address challenges weâd heard of from larger teams with mixed levels of Haskell expertise. If it helps enough of them significantly and doesnât impose unacceptable costs on hobbyists, researchers, enthusiasts, and teams of experts, then I think itâs a win - if not, then back to the drawing board!