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

Extension lifecycle framework proposal (under review) #601

Open
wants to merge 28 commits into
base: master
Choose a base branch
from
Open
Changes from 21 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
742b4e2
Add extension lifecycle framework proposal
david-christiansen Jul 4, 2023
d0bd5c5
Add the link to the PR
david-christiansen Jul 4, 2023
8d22d09
Fix broken link
david-christiansen Jul 4, 2023
6b1d8ed
Add discussion of expert vs non-expert users, and default warnings
david-christiansen Jul 12, 2023
d9aeede
Clarification about extension sets
david-christiansen Jul 12, 2023
8d0ee93
Rephrase for clarity
david-christiansen Jul 12, 2023
8cdbb8d
Add -WXLegacy to -Wall, and be more clear about default warnings
david-christiansen Jul 12, 2023
2c2749d
Respond to external tooling point
david-christiansen Jul 13, 2023
e1fcd2e
Incorporate text from Github thread RE warnings
david-christiansen Jul 13, 2023
d8aac07
Rename Mature to Stable
david-christiansen Aug 8, 2023
67bc9e4
The other changes
david-christiansen Aug 11, 2023
16ddbd1
Remove potentially-controversial example
david-christiansen Aug 11, 2023
d6c5bb2
Link to endorsements in thread
david-christiansen Aug 11, 2023
dc58067
Update proposals/0000-extension-lifecycle-framework.md
david-christiansen Aug 14, 2023
46b1e60
Rename Experimental to Unstable
david-christiansen Sep 1, 2023
1c05df4
Clarify comments in deprecations based on feedback
david-christiansen Sep 1, 2023
65639aa
Clarify that the transitions are non-normative
david-christiansen Sep 1, 2023
2fcc502
Respect -fshow-warning-groups
david-christiansen Sep 1, 2023
e7983b6
Address Simon's comments RE clarity and examples
david-christiansen Sep 1, 2023
362fa6e
Update proposal to be a smaller and more targeted at just the categor…
telser Mar 14, 2024
7fa95c4
Rename categorization to experimental
telser Apr 1, 2024
5460625
Updating formatting, wording, and links to related work based on feed…
telser Apr 7, 2024
e0c66e0
Addresses various feedback
telser May 5, 2024
0f30dbf
Add more transitions to the discretionary section
telser May 15, 2024
3db3a0d
Address various pieces of feedback for clarity, grammar, and punctuat…
telser May 26, 2024
12392ff
Address more feedback, correctly start new paragraph in markdown
telser May 26, 2024
3e5ef1c
Make category sections be uniform
telser May 26, 2024
7f3a801
Feedback from @JakobBruenker
telser May 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
110 changes: 110 additions & 0 deletions proposals/0000-extension-lifecycle-framework.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
---
author: Trevis Elser, Chris Dornan, David Thrane Christiansen
date-accepted: ""
ticket-url: ""
implemented: ""
---

This proposal is [discussed at this pull request](https://github.com/ghc-proposals/ghc-proposals/pull/601).

# Extension Lifecycle Framework

We propose a categorization scheme for Haskell language extensions. This scheme is simple, in that there are few categories that are described in terms of the user-relevant aspects. The purpose of this proposal is not to classify all extensions - rather, we seek to establish a basis upon which to carry out that work subsequently. Example classifications are provided to illustrate the proposed framework, and acceptance of this proposal should not count as acceptance these examples.
JakobBruenker marked this conversation as resolved.
Show resolved Hide resolved

## 1. Motivation

Since its inception, the Haskell programming language and GHC, its principal toolchain/development platform, has been open to innovation in programming language design through Haskell language extensions. The creation of those extensions has been well managed, giving rise to a programming language that is both coherent and still evolving and vital after more than three decades of astonishing development.

However, once an extension clears the review process and gets implemented in the compiler, there is currently no framework for understanding or managing its evolution. The strength of the development model is its openness, allowing experimental features to be tried out in the community. Features that the community discovers to be problematic in practice can be not enabled and the community can, over time, reach a consensus about the value of these extensions.

The weakness of this model is that, over time, the accumulation of programming extensions in various states of use and disuse can create confusion, especially for developers being introduced to Haskell. There is not one Haskell, but many, and each individual or team must necessarily choose their own. Not everyone has yet had the opportunity to accumulate the experience and knowledge that will allow them to quickly determine whether or not to use a given language extension, leading to various points of stress.

The authors of this proposal believe that a clear lifecycle for these programming language extensions would make it easier for newcomers, those responsible for onboarding new Haskell developers as well as managers, and the community more broadly, to make sense of the Haskell language extensions. This framework would make it clear which extensions are prone to rapid evolution, which of them are stable and suitable for serious use, and which of them are generally not considered suitable for new development.

## 2. Proposed Change Specification

### 2.1. Categories and Lifecycle
Language extensions will be classified into the following categories
Copy link
Contributor

Choose a reason for hiding this comment

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

A small point, but what about classifying "negative" extensions? For example FieldSelectors was effectively Stable when introduced (whereas NoFieldSelectors was definitely Experimental).

I guess the simplest thing would be to say that we classify both the enabled and disabled states, but the normal case is for an extension to be Stable when disabled (with NoFieldSelectors being one of a small number of exceptions).

* `Stable` 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 stable extension will be announced well in advance of the change being made, with a migration path provided if possible. For an extension to be classified as `Stable` it must be considered `Stable` when used in combination of all possible, non-mutually exclusive, extensions that are already `Stable`. This ensures any extension that is `Stable` will be have the same use without worry when combined with any other extension in the set, while allowing for mutually exclusive extensions to be added. Ideally, no breaking change will be made to a `Stable` extension, with incompatible changes resulting instead in a new, related extension, that is possibly mutually exclusive with the existing one, to enable smooth migration. Some extensions in this category might be `MultiWayIf`, `MonoLocalBinds`, and `ViewPatterns`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* `Stable` 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 stable extension will be announced well in advance of the change being made, with a migration path provided if possible. For an extension to be classified as `Stable` it must be considered `Stable` when used in combination of all possible, non-mutually exclusive, extensions that are already `Stable`. This ensures any extension that is `Stable` will be have the same use without worry when combined with any other extension in the set, while allowing for mutually exclusive extensions to be added. Ideally, no breaking change will be made to a `Stable` extension, with incompatible changes resulting instead in a new, related extension, that is possibly mutually exclusive with the existing one, to enable smooth migration. Some extensions in this category might be `MultiWayIf`, `MonoLocalBinds`, and `ViewPatterns`.
* `Stable` 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. More specifically
* For an extension to be classified as `Stable` it must be considered `Stable` when used in combination of all possible, non-mutually exclusive, extensions that are already `Stable`. This ensures any extension that is `Stable` will be have the same use without worry when combined with any other extension in the set, while allowing for mutually exclusive extensions to be added.
* Ideally, no breaking change will be made to a `Stable` extension. Instead, it may be better to add a new, related extension, that is possibly mutually exclusive with the existing one, to enable smooth migration.
* If, however, a breaking change is made to a stable extension, it will be announced well in advance of the change being made, with a migration path provided if possible.
* Some extensions in the `Stable` category might be `MultiWayIf`, `MonoLocalBinds`, and `ViewPatterns`.

Copy link
Contributor

Choose a reason for hiding this comment

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

"This ensures any extension that is Stable will be have the same use without worry " doe not parse.

Copy link
Contributor

Choose a reason for hiding this comment

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

Any thoughts on this?

Copy link

Choose a reason for hiding this comment

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

I thought the wording changed slightly in the last update but I must have put the existing one back before committing.
Perhaps:

This ensures any extension that is Stable will have the same stability properties when combined with any other extension in the set, while allowing for mutually exclusive extensions to be added.
?


* `Experimental` extensions are undergoing active development, or have consequences that make it impossible in practice to avoid breaking changes. The syntax and semantics that are enabled by the extension are likely to change regularly. It is expected that most new language extensions will begin as experimental, while the developers and the community gain experience with their use. Despite being open to breaking change, an `Experimental` extension must be `Deprecated` prior to removal. Some extensions in this category might be `RequiredTypeArguments`, `RebindableSyntax`, and `Arrows`.
simonpj marked this conversation as resolved.
Show resolved Hide resolved

* `Deprecated` extensions are considered to be design or implementation dead ends, and should not be used in new code. Deprecating an extension means that GHC intends to remove support for it in a future release (though this decision may be revised in the light of user feedback). When an extension is deprecated, the user's guide and the compiler warning _must_ include a statement about the longevity of the extension, though this need not necessarily commit to a concrete time for removal. Additionally, the user's guide and the warning should direct users to information about migrating away from the deprecated extension. Any extension will be deprecated prior to removal. Some extensions in this category might be `OverlappingInstances`, `Rank2Types`, `RecordPuns`, and `TypeInType`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* `Deprecated` extensions are considered to be design or implementation dead ends, and should not be used in new code. Deprecating an extension means that GHC intends to remove support for it in a future release (though this decision may be revised in the light of user feedback). When an extension is deprecated, the user's guide and the compiler warning _must_ include a statement about the longevity of the extension, though this need not necessarily commit to a concrete time for removal. Additionally, the user's guide and the warning should direct users to information about migrating away from the deprecated extension. Any extension will be deprecated prior to removal. Some extensions in this category might be `OverlappingInstances`, `Rank2Types`, `RecordPuns`, and `TypeInType`.
* `Deprecated` extensions are considered to be design or implementation dead ends, and should not be used in new code. Deprecating an extension means that GHC intends to remove support for it in a future release (though this decision may be revised in the light of user feedback).
* When an extension is deprecated, the user's guide and the compiler warning _must_ include a statement about the longevity of the extension, though this need not necessarily commit to a concrete time for removal. Additionally, the user's guide and the warning should direct users to information about migrating away from the deprecated extension.
* Any extension will be deprecated prior to removal.
* Some extensions in the `Deprecated` category might be `OverlappingInstances`, `Rank2Types`, `RecordPuns`, and `TypeInType`.

Copy link
Contributor

Choose a reason for hiding this comment

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

Formatting bug. The latter two bullets are over-indented

Copy link

Choose a reason for hiding this comment

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

Thank you, the last update should fix the formatting issue.


* `Legacy` extensions are explicitly not recommended for new code, much like `Deprecated`, however, they are expected to be supported indefinitely. This may be to maintain an older language set, maintain a bridge to a newer feature, or otherwise keep backward compatibility. Extensions that are `Legacy` may have some conflict with `Stable` extensions and explicitly do not need to be considered for an extension to be `Stable`. Some extensions in this category might be `CUSKs`, `DeepSubsumption`, and `NPlusKPatterns`.

Above we list expected categorizations of several extensions based on statements in the user's guide. We do not attempt to prescribe any particular categorizations as part of this proposal and simply provide a small number of expectations from the perspective of someone reading the existing documentation.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd say "several specific extensions"

Copy link

Choose a reason for hiding this comment

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

Made this change as well.


Copy link
Contributor

Choose a reason for hiding this comment

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

Start a new subection here: "Lifecycle: how an extension's category may change over time"

(And rename 2.1 to just "Categories"

Copy link

Choose a reason for hiding this comment

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

Done, thank you!

The above places some restrictions on the transitions included in the extension lifecycle. The following transitions are also expected to be included:
Copy link
Contributor

Choose a reason for hiding this comment

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

Please list all transitions. Otherwise what does "also" mean, precisely?

Or, perhaps better, list the excluded transitions, with some rationale.

Copy link
Contributor

Choose a reason for hiding this comment

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

I am keen to list all allowed transitions; or all disallowed transitions. Listing some of each, leaving others unspecified is not a happy state.

Copy link

Choose a reason for hiding this comment

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

Updated to list all transitions, including those not explicitly included or excluded in the proposal.

* `Experimental` -> `Stable`
* `Experimental` -> `Deprecated`
* `Experimental` -> `Legacy`
* `Stable` -> `Legacy`
* `Legacy` -> `Deprecated`

However, it also seems plausible that new knowledge might from time to time cause a stable extension to once again be considered experimental, e.g. in the face of soundness bugs or subtle interactions with other features. We explicitly allow for more transitions to allow for unforeseen circumstances. Restrictions are places on removal only. With this we aim to balance predictibility and flexibility. The consideration of both is important as extension classifications are first and foremost a communications channel between language designers, compiler developers, and users.
Copy link
Contributor

Choose a reason for hiding this comment

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

" Restrictions are places on removal only"

What precisely is the restriction?.

Copy link
Contributor

Choose a reason for hiding this comment

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

Any thoughts on this?

Copy link

Choose a reason for hiding this comment

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

I updated the set of included transitions to be more complete and added the exclusion list.

Copy link
Contributor

Choose a reason for hiding this comment

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

" We explicitly allow for more transitions". More than what? Can you make this precise?

Maybe you have in mind a set of "normal" transitions, ones that are "exceptional" and ones that are "disallowed"? I'm really not sure.

Copy link

Choose a reason for hiding this comment

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

Updated For this and the above to note the excluded transitions explicitly.

Copy link
Contributor

Choose a reason for hiding this comment

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

I can't see the change here.

Copy link

Choose a reason for hiding this comment

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

The explicitly excluded transitions are listed in the block right above this paragraph now.

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
However, it also seems plausible that new knowledge might from time to time cause a stable extension to once again be considered experimental, e.g. in the face of soundness bugs or subtle interactions with other features. We explicitly allow for more transitions to allow for unforeseen circumstances. Restrictions are places on removal only. With this we aim to balance predictibility and flexibility. The consideration of both is important as extension classifications are first and foremost a communications channel between language designers, compiler developers, and users.
However, it also seems plausible that new knowledge might from time to time cause a stable extension to once again be considered experimental, e.g. in the face of soundness bugs or subtle interactions with other features. We explicitly allow for more transitions to allow for unforeseen circumstances. Restrictions are placed on removal only. With this we aim to balance predictibility and flexibility. The consideration of both is important as extension classifications are first and foremost a communications channel between language designers, compiler developers, and users.

Copy link

Choose a reason for hiding this comment

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

Thanks again, this one should also be fixed now.


For existing, or future, language sets such as `GHC2021` or `Haskell98`, it is expected that none of the contained extensions would be `Experimental`. However, this proposal does not seek to impose any particular policy on the inclusion of extensions into language sets - the developers and the steering committee are always in the best position to make a decision about a concrete extension and extension set.
Copy link
Contributor

Choose a reason for hiding this comment

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

"language edition" not "language set"

Copy link

Choose a reason for hiding this comment

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

Thank you, updated!

Copy link
Contributor

Choose a reason for hiding this comment

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

It still says "language set"


Moving an extension through the lifecycle will require a GHC proposal. This will give users a chance to provide their input, it will help catch unexpected interactions (such as an `Stable` extension implying an `Experimental` one, and thus potentially allowing breakage at any moment), and it provides a way for language implementers and users to clarify their mutual expectations.

### 2.2. Documentation

The user's guide for each extension documents where it is in the extension lifecycle. We expect this to be next to the "Since" and "Implied by" fields in extension documentation. Additionally, the user's guide should provide a history of the extension's sojourn through the various states, and the GHC versions in which it went from being experimental to stable, or from stable to deprecated.
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do you pull out two particular transitions for special mention? Why not just say the user guide should document the GHC version in which each transition was made?

Copy link

Choose a reason for hiding this comment

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

I've updated the wording to make it more clear the guide should say when each transition was made and that two called out are examples.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see a change here


## 3. Effect and Interactions

The tension between large-scale industrial users of Haskell who desire stability and predictability and GHC's traditional role as a venue for language experiments is very real. This system addresses some of the industrial concern by providing clear communication to users that sets realistic expectations for language extensions.

Because this proposal does not change the semantics of any programs, we expect that it will not be a major disturbance.

## 4. Costs and Drawbacks

### 4.1. Development Costs

Development and ongoing costs are expected to exist primarily in the form of additional time to sufficiently warn users of upcoming changes, as well as creating and updating the status of extensions. We expect that the costs associated with moving an extension from one category to another will be small, but the discussion around doing so might take time - in particular, this may result in an increased workload for the GHC Steering Committee to process lifecycle transitions.

## 5. Alternatives

### 5.1. Include Another Categorization
Another categorization has been discussed at length to provide additional gradient for stability. An additional categorization could allow to further refine the notion of stability. Similarly, we could categorize in many different ways. However, adding any additional categories is left as a possible enhancement for the future, should a need or desire arise..
Copy link
Contributor

Choose a reason for hiding this comment

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

This para contains virtually no information. It would be far better to include a link to the discussion. Or just omit.

Copy link

Choose a reason for hiding this comment

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

I've removed it as I'm not sure the discussion, or at least a majority of it, was in a public space. Thank you again for all the great feedback.

JakobBruenker marked this conversation as resolved.
Show resolved Hide resolved

### 5.2. Adding Compiler Warnings

One alternative design is to add warnings to the compiler, instead of communicating about the status of extensions only in the User's Guide. We consider this to be likely to provide value, because users typically do not return to sections of the User's Guide that cover features that they already understand. The migration of an extension into a warning set provides a reason for them to consult the documentation. This is left as future work to be covered in other extensions.
Copy link
Contributor

Choose a reason for hiding this comment

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

what sort of warnings? Again this para is tantalising. It suggests an alternative but does not describe it. Link?

Copy link

Choose a reason for hiding this comment

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

It was in a previous revision of the proposal. Added some wording reflecting that. Not sure if a link to a previous revision is acceptable. If it is, I'm happy to add that or a link to some of the discussion around it that happened previously on this proposal.

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
One alternative design is to add warnings to the compiler, instead of communicating about the status of extensions only in the User's Guide. We consider this to be likely to provide value, because users typically do not return to sections of the User's Guide that cover features that they already understand. The migration of an extension into a warning set provides a reason for them to consult the documentation. This is left as future work to be covered in other extensions.
One alternative design is to add warnings to the compiler, instead of communicating about the status of extensions only in the User's Guide. We consider this to be likely to provide value, because users typically do not return to sections of the User's Guide that cover features that they already understand. The migration of an extension into a warning set provides a reason for them to consult the documentation. This is left as future work to be covered in other proposals.

Copy link

Choose a reason for hiding this comment

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

Thank you! Should be fixed now.


### 5.3. Implement Warnings and Categorizations Elsewhere

Warnings could additionally be implemented with a canonical configuration for a tool such as `hlint` or `stan`. Warnings from GHC itself have a number of advantages, however. First off, the categorization of extensions is maintained in one place, so teams don't need to construct and then maintain their own set. It's much easier to have a minor local deviation from an established standard than it is to create one. Secondly, compiler updates that change the status of an extension will trigger warnings without someone needing to remember to modify the configuration of an external linter, and projects that support a range of GHC versions will get the appropriate warnings for each version they run in CI without any extra configuration. And, perhaps most importantly, defaults matter most for less-experienced users. How would a new team know that they should install an extra linter and configure it this way? How would they decide between competing linter configurations? It seems valuable to provide them with something that basically reflects the consensus of the experts that comes by default.

### 5.4. Use Only Deprecations

Another alternative consists of not having an explicit lifecycle for extensions, but only adding deprecation warnings. This has the advantage of being a lighter-weight process that requires less from the developers of language extensions. Also, because any model necessarily neglects certain details, an implicit discussion of an extension's status provides space for more nuance. However, we believe that a simpler model that captures the world well enough is able to provide the vast majority of the information that's relevant to make decisions without incurring nearly as much of a cost in time and training as a fully-detailed and nuanced view (which can still be available in the documentation).

### 5.5. Lazily Add the `Deprecated` Set

It has been extremely rare that GHC actually removes an extension. This has been loudly signaled to the authors as a negative experience. It would be possible to refrain from adding the `Deprecated` category until it actually becomes needed. However, having this category (even if unused) serves important purposes:

1. Right now, the GHC documentation uses the term "deprecated" to refer both to things that are expected to disappear soon and to language extensions that are expected to remain for the forseeable future. Making it clear that these extensions are not facing imminent removal is valuable, and having the codified distinction helps communicate this.

2. The definition of an extension being `Stable` requires a deprecation process before removing it.

### 5.6 Conservativity Warnings and Syntactic vs Semantic Warnings

It would be possible to further classify extensions along two more dimensions:
* Whether they change the meaning of a program when enabled (such as `ScopedTypeVariables` and `MonoLocalBinds`) and those that add features without changing existing programs (such as `MultiWayIf`, `NPlusKPatterns`, and `LinearTypes`)
* Extensions that merely enable syntactic sugar (such as `MultiWayIf`, `NPlusKPatterns`, `DoAndIfThenElse`) and those that enrich the type system with new features (such as `DataKinds`, `TypeFamilies`, or `PolyKinds`).

This is clearly something that's desirable for users to know. However, this information is orthogonal to the stability, so we believe that mechanisms to communicate these aspects should be designed in a separate proposal.

## 6. Unresolved Questions


## 7. Implementation Plan

The Haskell Foundation will either recruit volunteers or pay for the technical work of implementing this proposal. The classifications of individual language extensions will be left to a future proposal, and those discussions can proceed while implementation is ongoing, should this proposal be accepted.
JakobBruenker marked this conversation as resolved.
Show resolved Hide resolved


## 8. Endorsements

A number of endorsements from industry users were provided for the prior version of this proposal in its [discussion thread](https://github.com/ghc-proposals/ghc-proposals/pull/601).