Dear GHC SC To avoid derailing the debate about -Wsevere <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, and HasField redesign <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, I'm starting a new (email for now) thread about stability. I have tried to articulate what I believe is an evolving consensus in this document <https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47ZulgaZds/edit?usp=sharing> . If we converge, we'll turn that into a proper PR for the GHC proposal process, although it has wider implications than just GHC proposals and we should share with a broader audience. But let's start with the steering committee. Any views? You all have edit rights. I think that the draft covers Moritz's and Julian's goals, at least that was my intention. I have pasted Moritz's last email below, for context. Simon ========= Moritz's last email ============ Now, this is derailing the original discussion a bit, and I'm not sure how far we want to take this. But, regarding @Simon Marlow <marlowsd@gmail.com>'s comment This is one cultural aspect of our community I'd like to shift: the
expectation that it's OK to make breaking changes as long as you warn about them or go through a migration cycle. It just isn't! (and I speak as someone who used to make lots of changes, I'm now fully repentant!). That's not to say that we shouldn't ever change anything, but when considering the cost/benefit tradeoff adding a migration cycle doesn't reduce the cost, it just defers it.
I actually read this as we should stop having breaking changes to begin with. And _if_ we do have breaking changes, that deprecation does not change the need to actually change code (cost). As outlined in my reply to that, and @Richard Eisenberg <lists@richarde.dev>'s observation, it "smears" the cost. The--to me--_much_ bigger implication of deprecation cycles is that we _inform_ our _customers_ about upcoming changes _early_, instead of _after the fact_. We also give them ample time to react. Being by changing their code, or raising their concerns. Would the Simplified Subsumptions / Deep Subsumptions change have looked differently? As such I see deprecation cycles as orthogonal to the question if we should have breaking changes to begin with. Thus I believe the following:
- Do have a deprecation cycle if possible. - Do not treat a deprecation cycle as an excuse. Costs are deferred but are as large as ever.
should be upgraded to: - Preferably _no_ breaking changes. - If breaking changes, then with a deprecation cycle, unless technically infeasible. - An understanding that any breaking change incurs significant costs. Ocaml recently added multicore support, and they put tremendous effort into making sure it keeps backwards compatibility: https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md PS: we should also agree that a "stable" extension should not require
dependencies on ghc-experimental. To become stable, any library support for an extension must move into `base`.
This seems like a good idea, however I still remain that _experimental_ features should not be on-by-default in a stable compiler. Yes, ideally I'd not even see them in a stable compiler, but I know this view is contentious. The use of `ghc-experimental` should therefore be guarded by `--std=experimental` as Julian suggested. That is a loud opt-in to experimental features.
Dear Simon, I want to thank you for taking the initiative of formulating this policy! Thank you! Best, Moritz On Fri, 22 Sept 2023 at 17:54, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Dear GHC SC
To avoid derailing the debate about -Wsevere <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, and HasField redesign <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, I'm starting a new (email for now) thread about stability.
I have tried to articulate what I believe is an evolving consensus in this document <https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47ZulgaZds/edit?usp=sharing> .
If we converge, we'll turn that into a proper PR for the GHC proposal process, although it has wider implications than just GHC proposals and we should share with a broader audience. But let's start with the steering committee.
Any views? You all have edit rights.
I think that the draft covers Moritz's and Julian's goals, at least that was my intention. I have pasted Moritz's last email below, for context.
Simon
========= Moritz's last email ============
Now, this is derailing the original discussion a bit, and I'm not sure how far we want to take this. But, regarding @Simon Marlow <marlowsd@gmail.com>'s comment
This is one cultural aspect of our community I'd like to shift: the
expectation that it's OK to make breaking changes as long as you warn about them or go through a migration cycle. It just isn't! (and I speak as someone who used to make lots of changes, I'm now fully repentant!). That's not to say that we shouldn't ever change anything, but when considering the cost/benefit tradeoff adding a migration cycle doesn't reduce the cost, it just defers it.
I actually read this as we should stop having breaking changes to begin with. And _if_ we do have breaking changes, that deprecation does not change the need to actually change code (cost). As outlined in my reply to that, and @Richard Eisenberg <lists@richarde.dev>'s observation, it "smears" the cost. The--to me--_much_ bigger implication of deprecation cycles is that we _inform_ our _customers_ about upcoming changes _early_, instead of _after the fact_. We also give them ample time to react. Being by changing their code, or raising their concerns. Would the Simplified Subsumptions / Deep Subsumptions change have looked differently? As such I see deprecation cycles as orthogonal to the question if we should have breaking changes to begin with.
Thus I believe the following:
- Do have a deprecation cycle if possible. - Do not treat a deprecation cycle as an excuse. Costs are deferred but are as large as ever.
should be upgraded to: - Preferably _no_ breaking changes. - If breaking changes, then with a deprecation cycle, unless technically infeasible. - An understanding that any breaking change incurs significant costs.
Ocaml recently added multicore support, and they put tremendous effort into making sure it keeps backwards compatibility: https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md
PS: we should also agree that a "stable" extension should not require
dependencies on ghc-experimental. To become stable, any library support for an extension must move into `base`.
This seems like a good idea, however I still remain that _experimental_ features should not be on-by-default in a stable compiler. Yes, ideally I'd not even see them in a stable compiler, but I know this view is contentious. The use of `ghc-experimental` should therefore be guarded by `--std=experimental` as Julian suggested. That is a loud opt-in to experimental features. _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
I like it a lot! Did some minor editing and added a comment. Cheers Simon On Fri, 22 Sept 2023 at 10:54, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Dear GHC SC
To avoid derailing the debate about -Wsevere <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, and HasField redesign <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, I'm starting a new (email for now) thread about stability.
I have tried to articulate what I believe is an evolving consensus in this document <https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47ZulgaZds/edit?usp=sharing> .
If we converge, we'll turn that into a proper PR for the GHC proposal process, although it has wider implications than just GHC proposals and we should share with a broader audience. But let's start with the steering committee.
Any views? You all have edit rights.
I think that the draft covers Moritz's and Julian's goals, at least that was my intention. I have pasted Moritz's last email below, for context.
Simon
========= Moritz's last email ============
Now, this is derailing the original discussion a bit, and I'm not sure how far we want to take this. But, regarding @Simon Marlow <marlowsd@gmail.com>'s comment
This is one cultural aspect of our community I'd like to shift: the
expectation that it's OK to make breaking changes as long as you warn about them or go through a migration cycle. It just isn't! (and I speak as someone who used to make lots of changes, I'm now fully repentant!). That's not to say that we shouldn't ever change anything, but when considering the cost/benefit tradeoff adding a migration cycle doesn't reduce the cost, it just defers it.
I actually read this as we should stop having breaking changes to begin with. And _if_ we do have breaking changes, that deprecation does not change the need to actually change code (cost). As outlined in my reply to that, and @Richard Eisenberg <lists@richarde.dev>'s observation, it "smears" the cost. The--to me--_much_ bigger implication of deprecation cycles is that we _inform_ our _customers_ about upcoming changes _early_, instead of _after the fact_. We also give them ample time to react. Being by changing their code, or raising their concerns. Would the Simplified Subsumptions / Deep Subsumptions change have looked differently? As such I see deprecation cycles as orthogonal to the question if we should have breaking changes to begin with.
Thus I believe the following:
- Do have a deprecation cycle if possible. - Do not treat a deprecation cycle as an excuse. Costs are deferred but are as large as ever.
should be upgraded to: - Preferably _no_ breaking changes. - If breaking changes, then with a deprecation cycle, unless technically infeasible. - An understanding that any breaking change incurs significant costs.
Ocaml recently added multicore support, and they put tremendous effort into making sure it keeps backwards compatibility: https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md
PS: we should also agree that a "stable" extension should not require
dependencies on ghc-experimental. To become stable, any library support for an extension must move into `base`.
This seems like a good idea, however I still remain that _experimental_ features should not be on-by-default in a stable compiler. Yes, ideally I'd not even see them in a stable compiler, but I know this view is contentious. The use of `ghc-experimental` should therefore be guarded by `--std=experimental` as Julian suggested. That is a loud opt-in to experimental features. _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
I liked it all the way down to GR3, which, for me, simply undermines GR1. Everybody who wants to make a breaking change has a good reason to make the change (at least in the minds of its adherents). Chris
On 22 Sep 2023, at 10:53, Simon Peyton Jones <simon.peytonjones@gmail.com> wrote:
Dear GHC SC
To avoid derailing the debate about -Wsevere <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, and HasField redesign <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, I'm starting a new (email for now) thread about stability.
I have tried to articulate what I believe is an evolving consensus in this document <https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47ZulgaZds/edit?usp=sharing>.
If we converge, we'll turn that into a proper PR for the GHC proposal process, although it has wider implications than just GHC proposals and we should share with a broader audience. But let's start with the steering committee.
Any views? You all have edit rights.
I think that the draft covers Moritz's and Julian's goals, at least that was my intention. I have pasted Moritz's last email below, for context.
Simon
========= Moritz's last email ============
Now, this is derailing the original discussion a bit, and I'm not sure how far we want to take this. But, regarding @Simon Marlow <mailto:marlowsd@gmail.com>'s comment
This is one cultural aspect of our community I'd like to shift: the expectation that it's OK to make breaking changes as long as you warn about them or go through a migration cycle. It just isn't! (and I speak as someone who used to make lots of changes, I'm now fully repentant!). That's not to say that we shouldn't ever change anything, but when considering the cost/benefit tradeoff adding a migration cycle doesn't reduce the cost, it just defers it.
I actually read this as we should stop having breaking changes to begin with. And _if_ we do have breaking changes, that deprecation does not change the need to actually change code (cost). As outlined in my reply to that, and @Richard Eisenberg <mailto:lists@richarde.dev>'s observation, it "smears" the cost. The--to me--_much_ bigger implication of deprecation cycles is that we _inform_ our _customers_ about upcoming changes _early_, instead of _after the fact_. We also give them ample time to react. Being by changing their code, or raising their concerns. Would the Simplified Subsumptions / Deep Subsumptions change have looked differently? As such I see deprecation cycles as orthogonal to the question if we should have breaking changes to begin with.
Thus I believe the following:
- Do have a deprecation cycle if possible. - Do not treat a deprecation cycle as an excuse. Costs are deferred but are as large as ever.
should be upgraded to: - Preferably _no_ breaking changes. - If breaking changes, then with a deprecation cycle, unless technically infeasible. - An understanding that any breaking change incurs significant costs.
Ocaml recently added multicore support, and they put tremendous effort into making sure it keeps backwards compatibility: https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md
PS: we should also agree that a "stable" extension should not require dependencies on ghc-experimental. To become stable, any library support for an extension must move into `base`.
This seems like a good idea, however I still remain that _experimental_ features should not be on-by-default in a stable compiler. Yes, ideally I'd not even see them in a stable compiler, but I know this view is contentious. The use of `ghc-experimental` should therefore be guarded by `--std=experimental` as Julian suggested. That is a loud opt-in to experimental features. _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
I liked it all the way down to GR3, which, for me, simply undermines GR1. Everybody who wants to make a breaking change has a good reason to make the change (at least in the minds of its adherents).
Can you elaborate? I don't understand. GR3 says simply "if you have a compelling (GR2) reason to break (GR1) then do whatever you can to mitigate the impact via a deprecation cycle". Why does that undermine GR1? Maybe you can rephrase (GR3)? Simon On Fri, 22 Sept 2023 at 12:39, Chris Dornan <chris@chrisdornan.com> wrote:
I liked it all the way down to GR3, which, for me, simply undermines GR1. Everybody who wants to make a breaking change has a good reason to make the change (at least in the minds of its adherents).
Chris
On 22 Sep 2023, at 10:53, Simon Peyton Jones <simon.peytonjones@gmail.com> wrote:
Dear GHC SC
To avoid derailing the debate about -Wsevere <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, and HasField redesign <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, I'm starting a new (email for now) thread about stability.
I have tried to articulate what I believe is an evolving consensus in this document <https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47ZulgaZds/edit?usp=sharing> .
If we converge, we'll turn that into a proper PR for the GHC proposal process, although it has wider implications than just GHC proposals and we should share with a broader audience. But let's start with the steering committee.
Any views? You all have edit rights.
I think that the draft covers Moritz's and Julian's goals, at least that was my intention. I have pasted Moritz's last email below, for context.
Simon
========= Moritz's last email ============
Now, this is derailing the original discussion a bit, and I'm not sure how far we want to take this. But, regarding @Simon Marlow <marlowsd@gmail.com>'s comment
This is one cultural aspect of our community I'd like to shift: the
expectation that it's OK to make breaking changes as long as you warn about them or go through a migration cycle. It just isn't! (and I speak as someone who used to make lots of changes, I'm now fully repentant!). That's not to say that we shouldn't ever change anything, but when considering the cost/benefit tradeoff adding a migration cycle doesn't reduce the cost, it just defers it.
I actually read this as we should stop having breaking changes to begin with. And _if_ we do have breaking changes, that deprecation does not change the need to actually change code (cost). As outlined in my reply to that, and @Richard Eisenberg <lists@richarde.dev>'s observation, it "smears" the cost. The--to me--_much_ bigger implication of deprecation cycles is that we _inform_ our _customers_ about upcoming changes _early_, instead of _after the fact_. We also give them ample time to react. Being by changing their code, or raising their concerns. Would the Simplified Subsumptions / Deep Subsumptions change have looked differently? As such I see deprecation cycles as orthogonal to the question if we should have breaking changes to begin with.
Thus I believe the following:
- Do have a deprecation cycle if possible. - Do not treat a deprecation cycle as an excuse. Costs are deferred but are as large as ever.
should be upgraded to: - Preferably _no_ breaking changes. - If breaking changes, then with a deprecation cycle, unless technically infeasible. - An understanding that any breaking change incurs significant costs.
Ocaml recently added multicore support, and they put tremendous effort into making sure it keeps backwards compatibility: https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md
PS: we should also agree that a "stable" extension should not require
dependencies on ghc-experimental. To become stable, any library support for an extension must move into `base`.
This seems like a good idea, however I still remain that _experimental_ features should not be on-by-default in a stable compiler. Yes, ideally I'd not even see them in a stable compiler, but I know this view is contentious. The use of `ghc-experimental` should therefore be guarded by `--std=experimental` as Julian suggested. That is a loud opt-in to experimental features. _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
I have added a comment in the doc saying a bit more, but I strongly believe we have to forswear, ever, electively introducing breaking changes inside such a proposed stability framework. Something might happen to force us to make a change but such contingencies are covered by the current text. Of course, experimental extensions can be subject to change, but this should, wherever possible, be done across deprecation cycles. Any other changes will simply fall outside this framework and should have to be argued for as such. I feel sure that we have enough tools at our disposal to make this work (see, for example, my suggestion for establishing #571 -Wsevere warnings as errors by default by capturing the behaviour in a language extension and rolling it into a future language standard). Chris
On 22 Sep 2023, at 13:08, Simon Peyton Jones <simon.peytonjones@gmail.com> wrote:
I liked it all the way down to GR3, which, for me, simply undermines GR1. Everybody who wants to make a breaking change has a good reason to make the change (at least in the minds of its adherents).
Can you elaborate? I don't understand. GR3 says simply "if you have a compelling (GR2) reason to break (GR1) then do whatever you can to mitigate the impact via a deprecation cycle". Why does that undermine GR1?
Maybe you can rephrase (GR3)?
Simon
On Fri, 22 Sept 2023 at 12:39, Chris Dornan <chris@chrisdornan.com <mailto:chris@chrisdornan.com>> wrote:
I liked it all the way down to GR3, which, for me, simply undermines GR1. Everybody who wants to make a breaking change has a good reason to make the change (at least in the minds of its adherents).
Chris
On 22 Sep 2023, at 10:53, Simon Peyton Jones <simon.peytonjones@gmail.com <mailto:simon.peytonjones@gmail.com>> wrote:
Dear GHC SC
To avoid derailing the debate about -Wsevere <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, and HasField redesign <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, I'm starting a new (email for now) thread about stability.
I have tried to articulate what I believe is an evolving consensus in this document <https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47ZulgaZds/edit?usp=sharing>.
If we converge, we'll turn that into a proper PR for the GHC proposal process, although it has wider implications than just GHC proposals and we should share with a broader audience. But let's start with the steering committee.
Any views? You all have edit rights.
I think that the draft covers Moritz's and Julian's goals, at least that was my intention. I have pasted Moritz's last email below, for context.
Simon
========= Moritz's last email ============
Now, this is derailing the original discussion a bit, and I'm not sure how far we want to take this. But, regarding @Simon Marlow <mailto:marlowsd@gmail.com>'s comment
This is one cultural aspect of our community I'd like to shift: the expectation that it's OK to make breaking changes as long as you warn about them or go through a migration cycle. It just isn't! (and I speak as someone who used to make lots of changes, I'm now fully repentant!). That's not to say that we shouldn't ever change anything, but when considering the cost/benefit tradeoff adding a migration cycle doesn't reduce the cost, it just defers it.
I actually read this as we should stop having breaking changes to begin with. And _if_ we do have breaking changes, that deprecation does not change the need to actually change code (cost). As outlined in my reply to that, and @Richard Eisenberg <mailto:lists@richarde.dev>'s observation, it "smears" the cost. The--to me--_much_ bigger implication of deprecation cycles is that we _inform_ our _customers_ about upcoming changes _early_, instead of _after the fact_. We also give them ample time to react. Being by changing their code, or raising their concerns. Would the Simplified Subsumptions / Deep Subsumptions change have looked differently? As such I see deprecation cycles as orthogonal to the question if we should have breaking changes to begin with.
Thus I believe the following:
- Do have a deprecation cycle if possible. - Do not treat a deprecation cycle as an excuse. Costs are deferred but are as large as ever.
should be upgraded to: - Preferably _no_ breaking changes. - If breaking changes, then with a deprecation cycle, unless technically infeasible. - An understanding that any breaking change incurs significant costs.
Ocaml recently added multicore support, and they put tremendous effort into making sure it keeps backwards compatibility: https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md
PS: we should also agree that a "stable" extension should not require dependencies on ghc-experimental. To become stable, any library support for an extension must move into `base`.
This seems like a good idea, however I still remain that _experimental_ features should not be on-by-default in a stable compiler. Yes, ideally I'd not even see them in a stable compiler, but I know this view is contentious. The use of `ghc-experimental` should therefore be guarded by `--std=experimental` as Julian suggested. That is a loud opt-in to experimental features. _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org <mailto:ghc-steering-committee@haskell.org> https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
I have added a comment in the doc saying a bit more, but I strongly believe we have to forswear, ever, electively introducing breaking changes inside such a proposed stability framework.
I feel I'm still misunderstanding you. Are you *really *saying that if we discover that (3+4) returns 8 we should forswear, ever, fixing that bug? (Fixing it is a breaking change.) Surely not. To take a slightly less caricature example, are you saying that we should never have done simple subsumption, but forever adopted deep subsumption, accepting the semantic unsoundness and technical debt that we would thereby accumulate, forever. Surely not? I don't think I'm ready to forswear breaking (GR1). But I agree that there should be a compelling reason. Maybe when you say "we should qualify it sufficiently that it is never broken", you mean that (GR1) should say General rule (GR1). A stable Haskell program that works today should continue to work in subsequent releases of GHC, *unless (GR2) applies*. Then, technically, breaking a stable program for a compelling reason doesn't break (GR1). But that's a bit of distinction without a difference! Simon On Fri, 22 Sept 2023 at 16:58, Chris Dornan <chris@chrisdornan.com> wrote:
I have added a comment in the doc saying a bit more, but I strongly believe we have to forswear, ever, electively introducing breaking changes inside such a proposed stability framework.
Something might happen to force us to make a change but such contingencies are covered by the current text.
Of course, experimental extensions can be subject to change, but this should, wherever possible, be done across deprecation cycles.
Any other changes will simply fall outside this framework and should have to be argued for as such.
I feel sure that we have enough tools at our disposal to make this work (see, for example, my suggestion for establishing #571 -Wsevere warnings as errors by default by capturing the behaviour in a language extension and rolling it into a future language standard).
Chris
On 22 Sep 2023, at 13:08, Simon Peyton Jones <simon.peytonjones@gmail.com> wrote:
I liked it all the way down to GR3, which, for me, simply undermines GR1.
Everybody who wants to make a breaking change has a good reason to make the change (at least in the minds of its adherents).
Can you elaborate? I don't understand. GR3 says simply "if you have a compelling (GR2) reason to break (GR1) then do whatever you can to mitigate the impact via a deprecation cycle". Why does that undermine GR1?
Maybe you can rephrase (GR3)?
Simon
On Fri, 22 Sept 2023 at 12:39, Chris Dornan <chris@chrisdornan.com> wrote:
I liked it all the way down to GR3, which, for me, simply undermines GR1. Everybody who wants to make a breaking change has a good reason to make the change (at least in the minds of its adherents).
Chris
On 22 Sep 2023, at 10:53, Simon Peyton Jones <simon.peytonjones@gmail.com> wrote:
Dear GHC SC
To avoid derailing the debate about -Wsevere <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, and HasField redesign <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, I'm starting a new (email for now) thread about stability.
I have tried to articulate what I believe is an evolving consensus in this document <https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47ZulgaZds/edit?usp=sharing> .
If we converge, we'll turn that into a proper PR for the GHC proposal process, although it has wider implications than just GHC proposals and we should share with a broader audience. But let's start with the steering committee.
Any views? You all have edit rights.
I think that the draft covers Moritz's and Julian's goals, at least that was my intention. I have pasted Moritz's last email below, for context.
Simon
========= Moritz's last email ============
Now, this is derailing the original discussion a bit, and I'm not sure how far we want to take this. But, regarding @Simon Marlow <marlowsd@gmail.com>'s comment
This is one cultural aspect of our community I'd like to shift: the
expectation that it's OK to make breaking changes as long as you warn about them or go through a migration cycle. It just isn't! (and I speak as someone who used to make lots of changes, I'm now fully repentant!). That's not to say that we shouldn't ever change anything, but when considering the cost/benefit tradeoff adding a migration cycle doesn't reduce the cost, it just defers it.
I actually read this as we should stop having breaking changes to begin with. And _if_ we do have breaking changes, that deprecation does not change the need to actually change code (cost). As outlined in my reply to that, and @Richard Eisenberg <lists@richarde.dev>'s observation, it "smears" the cost. The--to me--_much_ bigger implication of deprecation cycles is that we _inform_ our _customers_ about upcoming changes _early_, instead of _after the fact_. We also give them ample time to react. Being by changing their code, or raising their concerns. Would the Simplified Subsumptions / Deep Subsumptions change have looked differently? As such I see deprecation cycles as orthogonal to the question if we should have breaking changes to begin with.
Thus I believe the following:
- Do have a deprecation cycle if possible. - Do not treat a deprecation cycle as an excuse. Costs are deferred but are as large as ever.
should be upgraded to: - Preferably _no_ breaking changes. - If breaking changes, then with a deprecation cycle, unless technically infeasible. - An understanding that any breaking change incurs significant costs.
Ocaml recently added multicore support, and they put tremendous effort into making sure it keeps backwards compatibility: https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md
PS: we should also agree that a "stable" extension should not require
dependencies on ghc-experimental. To become stable, any library support for an extension must move into `base`.
This seems like a good idea, however I still remain that _experimental_ features should not be on-by-default in a stable compiler. Yes, ideally I'd not even see them in a stable compiler, but I know this view is contentious. The use of `ghc-experimental` should therefore be guarded by `--std=experimental` as Julian suggested. That is a loud opt-in to experimental features. _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
I have no problem at all with GR2, which covers the kind of unforeseen exceptional cases (3+4==>8, deep subsumption) we will need to be able to change. My confusion comes in interpreting GR3 -- I gained the impression that GR1, GR2 and GR3 are describing the various constraints on the changes that can be made with GR3 stipulating that if you need to break GR1 then this should be done with deprecation cycles. If GR3 is merely stipulating the way that GR2 changes should be rolled out (circumstances permitting) then I have no objection to GR3 at all -- except to suggest that it be tweaked to make it it explicit that it is elaborating on how GR2 changes should be deployed. I have refrained from making any changes to the text until I am sure I understand what we wish to convey. Chris
On 22 Sep 2023, at 17:32, Simon Peyton Jones <simon.peytonjones@gmail.com> wrote:
I have added a comment in the doc saying a bit more, but I strongly believe we have to forswear, ever, electively introducing breaking changes inside such a proposed stability framework.
I feel I'm still misunderstanding you.
Are you really saying that if we discover that (3+4) returns 8 we should forswear, ever, fixing that bug? (Fixing it is a breaking change.) Surely not.
To take a slightly less caricature example, are you saying that we should never have done simple subsumption, but forever adopted deep subsumption, accepting the semantic unsoundness and technical debt that we would thereby accumulate, forever. Surely not?
I don't think I'm ready to forswear breaking (GR1). But I agree that there should be a compelling reason.
Maybe when you say "we should qualify it sufficiently that it is never broken", you mean that (GR1) should say
General rule (GR1). A stable Haskell program that works today should continue to work in subsequent releases of GHC, unless (GR2) applies.
Then, technically, breaking a stable program for a compelling reason doesn't break (GR1). But that's a bit of distinction without a difference!
Simon
On Fri, 22 Sept 2023 at 16:58, Chris Dornan <chris@chrisdornan.com <mailto:chris@chrisdornan.com>> wrote:
I have added a comment in the doc saying a bit more, but I strongly believe we have to forswear, ever, electively introducing breaking changes inside such a proposed stability framework.
Something might happen to force us to make a change but such contingencies are covered by the current text.
Of course, experimental extensions can be subject to change, but this should, wherever possible, be done across deprecation cycles.
Any other changes will simply fall outside this framework and should have to be argued for as such.
I feel sure that we have enough tools at our disposal to make this work (see, for example, my suggestion for establishing #571 -Wsevere warnings as errors by default by capturing the behaviour in a language extension and rolling it into a future language standard).
Chris
On 22 Sep 2023, at 13:08, Simon Peyton Jones <simon.peytonjones@gmail.com <mailto:simon.peytonjones@gmail.com>> wrote:
I liked it all the way down to GR3, which, for me, simply undermines GR1. Everybody who wants to make a breaking change has a good reason to make the change (at least in the minds of its adherents).
Can you elaborate? I don't understand. GR3 says simply "if you have a compelling (GR2) reason to break (GR1) then do whatever you can to mitigate the impact via a deprecation cycle". Why does that undermine GR1?
Maybe you can rephrase (GR3)?
Simon
On Fri, 22 Sept 2023 at 12:39, Chris Dornan <chris@chrisdornan.com <mailto:chris@chrisdornan.com>> wrote:
I liked it all the way down to GR3, which, for me, simply undermines GR1. Everybody who wants to make a breaking change has a good reason to make the change (at least in the minds of its adherents).
Chris
On 22 Sep 2023, at 10:53, Simon Peyton Jones <simon.peytonjones@gmail.com <mailto:simon.peytonjones@gmail.com>> wrote:
Dear GHC SC
To avoid derailing the debate about -Wsevere <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, and HasField redesign <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, I'm starting a new (email for now) thread about stability.
I have tried to articulate what I believe is an evolving consensus in this document <https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47ZulgaZds/edit?usp=sharing>.
If we converge, we'll turn that into a proper PR for the GHC proposal process, although it has wider implications than just GHC proposals and we should share with a broader audience. But let's start with the steering committee.
Any views? You all have edit rights.
I think that the draft covers Moritz's and Julian's goals, at least that was my intention. I have pasted Moritz's last email below, for context.
Simon
========= Moritz's last email ============
Now, this is derailing the original discussion a bit, and I'm not sure how far we want to take this. But, regarding @Simon Marlow <mailto:marlowsd@gmail.com>'s comment
This is one cultural aspect of our community I'd like to shift: the expectation that it's OK to make breaking changes as long as you warn about them or go through a migration cycle. It just isn't! (and I speak as someone who used to make lots of changes, I'm now fully repentant!). That's not to say that we shouldn't ever change anything, but when considering the cost/benefit tradeoff adding a migration cycle doesn't reduce the cost, it just defers it.
I actually read this as we should stop having breaking changes to begin with. And _if_ we do have breaking changes, that deprecation does not change the need to actually change code (cost). As outlined in my reply to that, and @Richard Eisenberg <mailto:lists@richarde.dev>'s observation, it "smears" the cost. The--to me--_much_ bigger implication of deprecation cycles is that we _inform_ our _customers_ about upcoming changes _early_, instead of _after the fact_. We also give them ample time to react. Being by changing their code, or raising their concerns. Would the Simplified Subsumptions / Deep Subsumptions change have looked differently? As such I see deprecation cycles as orthogonal to the question if we should have breaking changes to begin with.
Thus I believe the following:
- Do have a deprecation cycle if possible. - Do not treat a deprecation cycle as an excuse. Costs are deferred but are as large as ever.
should be upgraded to: - Preferably _no_ breaking changes. - If breaking changes, then with a deprecation cycle, unless technically infeasible. - An understanding that any breaking change incurs significant costs.
Ocaml recently added multicore support, and they put tremendous effort into making sure it keeps backwards compatibility: https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md
PS: we should also agree that a "stable" extension should not require dependencies on ghc-experimental. To become stable, any library support for an extension must move into `base`.
This seems like a good idea, however I still remain that _experimental_ features should not be on-by-default in a stable compiler. Yes, ideally I'd not even see them in a stable compiler, but I know this view is contentious. The use of `ghc-experimental` should therefore be guarded by `--std=experimental` as Julian suggested. That is a loud opt-in to experimental features. _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org <mailto:ghc-steering-committee@haskell.org> https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
I'm afraid that I'm somewhat sceptical of this approach. A strong stability guarantee is certainly a valuable goal, but it also comes with costs, which I'd like to see more clearly articulated. Some of them include: * Cognitive overhead for users, because of the inability to remove complexity from the design. * Increasing maintenance burden in the compiler, because of the additional work needed to implement new features and the inability to remove complexity from the implementation. * A risk of getting stuck in a local optimum, because moving to a better design would entail breaking changes. * Discouraging volunteer contributors, who are much less likely to work on a potentially beneficial change if the process for getting it approved is too onerous. (I'm worried we're already reaching that point due to the increasing burden of well-intentioned processes.) Ultimately every proposed change has a cost-benefit trade-off, with risk of breakage being one of the costs. We need to consciously evaluate that trade-off on a case-by-case basis. Almost all changes might break something (e.g. by regressing performance, or for Hyrum's Law reasons), so there needs to be a proportionate assessment of how likely each change is to be damaging in practice, bearing in mind that such an assessment is itself costly and limited in scope. It seems to me that the GHC team have taken on board lessons regarding stability of the language, and the extension system already gives quite a lot of flexibility to evolve the language in a backwards-compatible way. In my experience, the key stability problems preventing upgrades to recent GHC releases are: * The cascading effect of breaking changes in one library causing the need to upgrade libraries which depend upon it. This is primarily under the control of the CLC and library maintainers, however, not the GHC team. It would help if base was minimal and reinstallable, but that isn't a total solution either, because you'd still have to worry about packages depending on template-haskell or the ghc package itself. * Performance regressions or critical bugs. These tend to be a significant obstacle to upgrading for smaller commercial users. But spending more of our limited resources on stability of the language means fewer resources for resolving these issues. There's surely more we can do here, but let's be careful not to pay too many costs to achieve stability of the *language* alone, when stability of the *libraries* and *implementation* are both more important and harder to fix. Adam On 22/09/2023 10:53, Simon Peyton Jones wrote:
Dear GHC SC
To avoid derailing the debate about -Wsevere <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, and HasField redesign <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, I'm starting a new (email for now) thread about stability.
I have tried to articulate what I believe is an evolving consensus in this document <https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47ZulgaZds/edit?usp=sharing>.
If we converge, we'll turn that into a proper PR for the GHC proposal process, although it has wider implications than just GHC proposals and we should share with a broader audience. But let's start with the steering committee.
Any views? You all have edit rights.
I think that the draft covers Moritz's and Julian's goals, at least that was my intention. I have pasted Moritz's last email below, for context.
Simon
========= Moritz's last email ============
Now, this is derailing the original discussion a bit, and I'm not sure how far we want to take this. But, regarding @Simon Marlow <mailto:marlowsd@gmail.com>'s comment
This is one cultural aspect of our community I'd like to shift: the expectation that it's OK to make breaking changes as long as you warn about them or go through a migration cycle. It just isn't! (and I speak as someone who used to make lots of changes, I'm now fully repentant!). That's not to say that we shouldn't ever change anything, but when considering the cost/benefit tradeoff adding a migration cycle doesn't reduce the cost, it just defers it.
I actually read this as we should stop having breaking changes to begin with. And _if_ we do have breaking changes, that deprecation does not change the need to actually change code (cost). As outlined in my reply to that, and @Richard Eisenberg <mailto:lists@richarde.dev>'s observation, it "smears" the cost. The--to me--_much_ bigger implication of deprecation cycles is that we _inform_ our _customers_ about upcoming changes _early_, instead of _after the fact_. We also give them ample time to react. Being by changing their code, or raising their concerns. Would the Simplified Subsumptions / Deep Subsumptions change have looked differently? As such I see deprecation cycles as orthogonal to the question if we should have breaking changes to begin with.
Thus I believe the following:
- Do have a deprecation cycle if possible. - Do not treat a deprecation cycle as an excuse. Costs are deferred but are as large as ever.
should be upgraded to: - Preferably _no_ breaking changes. - If breaking changes, then with a deprecation cycle, unless technically infeasible. - An understanding that any breaking change incurs significant costs.
Ocaml recently added multicore support, and they put tremendous effort into making sure it keeps backwards compatibility: https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md <https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md>
PS: we should also agree that a "stable" extension should not require dependencies on ghc-experimental. To become stable, any library support for an extension must move into `base`.
This seems like a good idea, however I still remain that _experimental_ features should not be on-by-default in a stable compiler. Yes, ideally I'd not even see them in a stable compiler, but I know this view is contentious. The use of `ghc-experimental` should therefore be guarded by `--std=experimental` as Julian suggested. That is a loud opt-in to experimental features.
-- Adam Gundry, Haskell Consultant Well-Typed LLP, https://www.well-typed.com/ Registered in England & Wales, OC335890 27 Old Gloucester Street, London WC1N 3AX, England
A strong stability guarantee is certainly a valuable goal, but it also comes with costs, which I'd like to see more clearly articulated. Some of them include:
Thanks for articulating this. I see this doc as the language counterpart of the base-libraries document, where we split `base` and `ghc-experimental`. By splitting in this way, we allow innovation, while placing stronger stability goals on `base`. Stronger, but not unbreakable: I expect base to continue to evolve, e.g. by removing (with deprecation cycles) stuff that is plainly GHC-internal, subject to the CLC. But, as we have seen in the extensive debate that led up to this proposal, it is *really *helpful to have a clear line between "experimental" and "stable", for all sorts of reasons. I think we are just doing the same here. Many GHC proposals add a new language feature, guarded by an extension, and are unaffected by the proposal. Others make changes to recently added extensions (Linear Haskell is the poster child example), which we informally regard as experimental and subject to change. But we don't *say* that at the moment... it's all informal. By identifying which extensions are experimental, and which are stable (and subject to higher back-compat goals) we help our users, and ourselves. Just like base vs ghc-experimental. I called them "General Rules" because (just like changes to base) I think we will want to break them. But I'm content to be considerably more careful when we break stable extensions than experimental ones. ============= Template Haskell is a real problem. I don't think we can promise never to change TH syntax, for the reasons you describe. Is it true that many TH users use only splices and quotations, not explicit use of TH data constructors? Those programs should be much more stable. For ones that use TH data constructors I think that prompt (but very routine) maintenance may be needed. Simon On Mon, 25 Sept 2023 at 08:17, Adam Gundry <adam@well-typed.com> wrote:
I'm afraid that I'm somewhat sceptical of this approach.
A strong stability guarantee is certainly a valuable goal, but it also comes with costs, which I'd like to see more clearly articulated. Some of them include:
* Cognitive overhead for users, because of the inability to remove complexity from the design.
* Increasing maintenance burden in the compiler, because of the additional work needed to implement new features and the inability to remove complexity from the implementation.
* A risk of getting stuck in a local optimum, because moving to a better design would entail breaking changes.
* Discouraging volunteer contributors, who are much less likely to work on a potentially beneficial change if the process for getting it approved is too onerous. (I'm worried we're already reaching that point due to the increasing burden of well-intentioned processes.)
Ultimately every proposed change has a cost-benefit trade-off, with risk of breakage being one of the costs. We need to consciously evaluate that trade-off on a case-by-case basis. Almost all changes might break something (e.g. by regressing performance, or for Hyrum's Law reasons), so there needs to be a proportionate assessment of how likely each change is to be damaging in practice, bearing in mind that such an assessment is itself costly and limited in scope.
It seems to me that the GHC team have taken on board lessons regarding stability of the language, and the extension system already gives quite a lot of flexibility to evolve the language in a backwards-compatible way. In my experience, the key stability problems preventing upgrades to recent GHC releases are:
* The cascading effect of breaking changes in one library causing the need to upgrade libraries which depend upon it. This is primarily under the control of the CLC and library maintainers, however, not the GHC team. It would help if base was minimal and reinstallable, but that isn't a total solution either, because you'd still have to worry about packages depending on template-haskell or the ghc package itself.
* Performance regressions or critical bugs. These tend to be a significant obstacle to upgrading for smaller commercial users. But spending more of our limited resources on stability of the language means fewer resources for resolving these issues.
There's surely more we can do here, but let's be careful not to pay too many costs to achieve stability of the *language* alone, when stability of the *libraries* and *implementation* are both more important and harder to fix.
Adam
On 22/09/2023 10:53, Simon Peyton Jones wrote:
Dear GHC SC
To avoid derailing the debate about -Wsevere < https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, and HasField redesign < https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, I'm starting a new (email for now) thread about stability.
I have tried to articulate what I believe is an evolving consensus in this document < https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47Zulga... .
If we converge, we'll turn that into a proper PR for the GHC proposal process, although it has wider implications than just GHC proposals and we should share with a broader audience. But let's start with the steering committee.
Any views? You all have edit rights.
I think that the draft covers Moritz's and Julian's goals, at least that was my intention. I have pasted Moritz's last email below, for context.
Simon
========= Moritz's last email ============
Now, this is derailing the original discussion a bit, and I'm not sure how far we want to take this. But, regarding @Simon Marlow <mailto:marlowsd@gmail.com>'s comment
This is one cultural aspect of our community I'd like to shift: the expectation that it's OK to make breaking changes as long as you warn about them or go through a migration cycle. It just isn't! (and I speak as someone who used to make lots of changes, I'm now fully repentant!). That's not to say that we shouldn't ever change anything, but when considering the cost/benefit tradeoff adding a migration cycle doesn't reduce the cost, it just defers it.
I actually read this as we should stop having breaking changes to begin with. And _if_ we do have breaking changes, that deprecation does not change the need to actually change code (cost). As outlined in my reply to that, and @Richard Eisenberg <mailto:lists@richarde.dev>'s observation, it "smears" the cost. The--to me--_much_ bigger implication of deprecation cycles is that we _inform_ our _customers_ about upcoming changes _early_, instead of _after the fact_. We also give them ample time to react. Being by changing their code, or raising their concerns. Would the Simplified Subsumptions / Deep Subsumptions change have looked differently? As such I see deprecation cycles as orthogonal to the question if we should have breaking changes to begin with.
Thus I believe the following:
- Do have a deprecation cycle if possible. - Do not treat a deprecation cycle as an excuse. Costs are deferred but are as large as ever.
should be upgraded to: - Preferably _no_ breaking changes. - If breaking changes, then with a deprecation cycle, unless technically infeasible. - An understanding that any breaking change incurs significant costs.
Ocaml recently added multicore support, and they put tremendous effort into making sure it keeps backwards compatibility: https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md <https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md>
PS: we should also agree that a "stable" extension should not require dependencies on ghc-experimental. To become stable, any library support for an extension must move into `base`.
This seems like a good idea, however I still remain that _experimental_ features should not be on-by-default in a stable compiler. Yes, ideally I'd not even see them in a stable compiler, but I know this view is contentious. The use of `ghc-experimental` should therefore be guarded by `--std=experimental` as Julian suggested. That is a loud opt-in to experimental features.
-- Adam Gundry, Haskell Consultant Well-Typed LLP, https://www.well-typed.com/
Registered in England & Wales, OC335890 27 Old Gloucester Street, London WC1N 3AX, England
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
In a discussion with Simon this morning, we realized that the document does two separable things: 1. It articulates a set of rules for what stability guarantees GHC should strive for 2. It articulates a possible enforcement mechanism for Haskellers to opt for the stable subset of GHC/Haskelll It is possible to adopt (1) without (2). Indeed I worry that (2) would require much of the structure that we have already seen in Safe Haskell: a way to mark a package as "stable-interface" that somehow promises always to work, even though it uses experimental features internally. This will be necessary for `base`, for example, but I imagine other packages, too. But even (1) on its own would at least align the committee and make forward progress easier to talk about. I'm not necessarily against (2) -- just wanted to highlight that the two notions are separable. Richard
On Sep 25, 2023, at 4:46 AM, Simon Peyton Jones <simon.peytonjones@gmail.com> wrote:
A strong stability guarantee is certainly a valuable goal, but it also comes with costs, which I'd like to see more clearly articulated. Some of them include:
Thanks for articulating this.
I see this doc as the language counterpart of the base-libraries document, where we split `base` and `ghc-experimental`. By splitting in this way, we allow innovation, while placing stronger stability goals on `base`. Stronger, but not unbreakable: I expect base to continue to evolve, e.g. by removing (with deprecation cycles) stuff that is plainly GHC-internal, subject to the CLC. But, as we have seen in the extensive debate that led up to this proposal, it is really helpful to have a clear line between "experimental" and "stable", for all sorts of reasons.
I think we are just doing the same here. Many GHC proposals add a new language feature, guarded by an extension, and are unaffected by the proposal. Others make changes to recently added extensions (Linear Haskell is the poster child example), which we informally regard as experimental and subject to change. But we don't *say* that at the moment... it's all informal. By identifying which extensions are experimental, and which are stable (and subject to higher back-compat goals) we help our users, and ourselves. Just like base vs ghc-experimental.
I called them "General Rules" because (just like changes to base) I think we will want to break them. But I'm content to be considerably more careful when we break stable extensions than experimental ones.
=============
Template Haskell is a real problem. I don't think we can promise never to change TH syntax, for the reasons you describe.
Is it true that many TH users use only splices and quotations, not explicit use of TH data constructors? Those programs should be much more stable.
For ones that use TH data constructors I think that prompt (but very routine) maintenance may be needed.
Simon
On Mon, 25 Sept 2023 at 08:17, Adam Gundry <adam@well-typed.com <mailto:adam@well-typed.com>> wrote: I'm afraid that I'm somewhat sceptical of this approach.
A strong stability guarantee is certainly a valuable goal, but it also comes with costs, which I'd like to see more clearly articulated. Some of them include:
* Cognitive overhead for users, because of the inability to remove complexity from the design.
* Increasing maintenance burden in the compiler, because of the additional work needed to implement new features and the inability to remove complexity from the implementation.
* A risk of getting stuck in a local optimum, because moving to a better design would entail breaking changes.
* Discouraging volunteer contributors, who are much less likely to work on a potentially beneficial change if the process for getting it approved is too onerous. (I'm worried we're already reaching that point due to the increasing burden of well-intentioned processes.)
Ultimately every proposed change has a cost-benefit trade-off, with risk of breakage being one of the costs. We need to consciously evaluate that trade-off on a case-by-case basis. Almost all changes might break something (e.g. by regressing performance, or for Hyrum's Law reasons), so there needs to be a proportionate assessment of how likely each change is to be damaging in practice, bearing in mind that such an assessment is itself costly and limited in scope.
It seems to me that the GHC team have taken on board lessons regarding stability of the language, and the extension system already gives quite a lot of flexibility to evolve the language in a backwards-compatible way. In my experience, the key stability problems preventing upgrades to recent GHC releases are:
* The cascading effect of breaking changes in one library causing the need to upgrade libraries which depend upon it. This is primarily under the control of the CLC and library maintainers, however, not the GHC team. It would help if base was minimal and reinstallable, but that isn't a total solution either, because you'd still have to worry about packages depending on template-haskell or the ghc package itself.
* Performance regressions or critical bugs. These tend to be a significant obstacle to upgrading for smaller commercial users. But spending more of our limited resources on stability of the language means fewer resources for resolving these issues.
There's surely more we can do here, but let's be careful not to pay too many costs to achieve stability of the *language* alone, when stability of the *libraries* and *implementation* are both more important and harder to fix.
Adam
On 22/09/2023 10:53, Simon Peyton Jones wrote:
Dear GHC SC
To avoid derailing the debate about -Wsevere <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003... <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>>, and HasField redesign <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003... <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>>, I'm starting a new (email for now) thread about stability.
I have tried to articulate what I believe is an evolving consensus in this document <https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47Zulga... <https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47ZulgaZds/edit?usp=sharing>>.
If we converge, we'll turn that into a proper PR for the GHC proposal process, although it has wider implications than just GHC proposals and we should share with a broader audience. But let's start with the steering committee.
Any views? You all have edit rights.
I think that the draft covers Moritz's and Julian's goals, at least that was my intention. I have pasted Moritz's last email below, for context.
Simon
========= Moritz's last email ============
Now, this is derailing the original discussion a bit, and I'm not sure how far we want to take this. But, regarding @Simon Marlow <mailto:marlowsd@gmail.com <mailto:marlowsd@gmail.com>>'s comment
This is one cultural aspect of our community I'd like to shift: the expectation that it's OK to make breaking changes as long as you warn about them or go through a migration cycle. It just isn't! (and I speak as someone who used to make lots of changes, I'm now fully repentant!). That's not to say that we shouldn't ever change anything, but when considering the cost/benefit tradeoff adding a migration cycle doesn't reduce the cost, it just defers it.
I actually read this as we should stop having breaking changes to begin with. And _if_ we do have breaking changes, that deprecation does not change the need to actually change code (cost). As outlined in my reply to that, and @Richard Eisenberg <mailto:lists@richarde.dev <mailto:lists@richarde.dev>>'s observation, it "smears" the cost. The--to me--_much_ bigger implication of deprecation cycles is that we _inform_ our _customers_ about upcoming changes _early_, instead of _after the fact_. We also give them ample time to react. Being by changing their code, or raising their concerns. Would the Simplified Subsumptions / Deep Subsumptions change have looked differently? As such I see deprecation cycles as orthogonal to the question if we should have breaking changes to begin with.
Thus I believe the following:
- Do have a deprecation cycle if possible. - Do not treat a deprecation cycle as an excuse. Costs are deferred but are as large as ever.
should be upgraded to: - Preferably _no_ breaking changes. - If breaking changes, then with a deprecation cycle, unless technically infeasible. - An understanding that any breaking change incurs significant costs.
Ocaml recently added multicore support, and they put tremendous effort into making sure it keeps backwards compatibility: https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md <https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md> <https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md <https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md>>
PS: we should also agree that a "stable" extension should not require dependencies on ghc-experimental. To become stable, any library support for an extension must move into `base`.
This seems like a good idea, however I still remain that _experimental_ features should not be on-by-default in a stable compiler. Yes, ideally I'd not even see them in a stable compiler, but I know this view is contentious. The use of `ghc-experimental` should therefore be guarded by `--std=experimental` as Julian suggested. That is a loud opt-in to experimental features.
-- Adam Gundry, Haskell Consultant Well-Typed LLP, https://www.well-typed.com/ <https://www.well-typed.com/>
Registered in England & Wales, OC335890 27 Old Gloucester Street, London WC1N 3AX, England
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org <mailto:ghc-steering-committee@haskell.org> https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee <https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee> _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
In a discussion with Simon this morning, we realized that the document does two separable things:
1. It articulates a set of rules for what stability guarantees GHC should strive for 2. It articulates a possible enforcement mechanism for Haskellers to opt for the stable subset of GHC/Haskelll
...and I have reflected this observation in the doc by pulling out (2) into a new Section 6. Simon On Mon, 25 Sept 2023 at 14:36, Richard Eisenberg <lists@richarde.dev> wrote:
In a discussion with Simon this morning, we realized that the document does two separable things:
1. It articulates a set of rules for what stability guarantees GHC should strive for 2. It articulates a possible enforcement mechanism for Haskellers to opt for the stable subset of GHC/Haskelll
It is possible to adopt (1) without (2). Indeed I worry that (2) would require much of the structure that we have already seen in Safe Haskell: a way to mark a package as "stable-interface" that somehow promises always to work, even though it uses experimental features internally. This will be necessary for `base`, for example, but I imagine other packages, too.
But even (1) on its own would at least align the committee and make forward progress easier to talk about.
I'm not necessarily against (2) -- just wanted to highlight that the two notions are separable.
Richard
On Sep 25, 2023, at 4:46 AM, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
A strong stability guarantee is certainly a valuable goal, but it also
comes with costs, which I'd like to see more clearly articulated. Some of them include:
Thanks for articulating this.
I see this doc as the language counterpart of the base-libraries document, where we split `base` and `ghc-experimental`. By splitting in this way, we allow innovation, while placing stronger stability goals on `base`. Stronger, but not unbreakable: I expect base to continue to evolve, e.g. by removing (with deprecation cycles) stuff that is plainly GHC-internal, subject to the CLC. But, as we have seen in the extensive debate that led up to this proposal, it is *really *helpful to have a clear line between "experimental" and "stable", for all sorts of reasons.
I think we are just doing the same here. Many GHC proposals add a new language feature, guarded by an extension, and are unaffected by the proposal. Others make changes to recently added extensions (Linear Haskell is the poster child example), which we informally regard as experimental and subject to change. But we don't *say* that at the moment... it's all informal. By identifying which extensions are experimental, and which are stable (and subject to higher back-compat goals) we help our users, and ourselves. Just like base vs ghc-experimental.
I called them "General Rules" because (just like changes to base) I think we will want to break them. But I'm content to be considerably more careful when we break stable extensions than experimental ones.
=============
Template Haskell is a real problem. I don't think we can promise never to change TH syntax, for the reasons you describe.
Is it true that many TH users use only splices and quotations, not explicit use of TH data constructors? Those programs should be much more stable.
For ones that use TH data constructors I think that prompt (but very routine) maintenance may be needed.
Simon
On Mon, 25 Sept 2023 at 08:17, Adam Gundry <adam@well-typed.com> wrote:
I'm afraid that I'm somewhat sceptical of this approach.
A strong stability guarantee is certainly a valuable goal, but it also comes with costs, which I'd like to see more clearly articulated. Some of them include:
* Cognitive overhead for users, because of the inability to remove complexity from the design.
* Increasing maintenance burden in the compiler, because of the additional work needed to implement new features and the inability to remove complexity from the implementation.
* A risk of getting stuck in a local optimum, because moving to a better design would entail breaking changes.
* Discouraging volunteer contributors, who are much less likely to work on a potentially beneficial change if the process for getting it approved is too onerous. (I'm worried we're already reaching that point due to the increasing burden of well-intentioned processes.)
Ultimately every proposed change has a cost-benefit trade-off, with risk of breakage being one of the costs. We need to consciously evaluate that trade-off on a case-by-case basis. Almost all changes might break something (e.g. by regressing performance, or for Hyrum's Law reasons), so there needs to be a proportionate assessment of how likely each change is to be damaging in practice, bearing in mind that such an assessment is itself costly and limited in scope.
It seems to me that the GHC team have taken on board lessons regarding stability of the language, and the extension system already gives quite a lot of flexibility to evolve the language in a backwards-compatible way. In my experience, the key stability problems preventing upgrades to recent GHC releases are:
* The cascading effect of breaking changes in one library causing the need to upgrade libraries which depend upon it. This is primarily under the control of the CLC and library maintainers, however, not the GHC team. It would help if base was minimal and reinstallable, but that isn't a total solution either, because you'd still have to worry about packages depending on template-haskell or the ghc package itself.
* Performance regressions or critical bugs. These tend to be a significant obstacle to upgrading for smaller commercial users. But spending more of our limited resources on stability of the language means fewer resources for resolving these issues.
There's surely more we can do here, but let's be careful not to pay too many costs to achieve stability of the *language* alone, when stability of the *libraries* and *implementation* are both more important and harder to fix.
Adam
On 22/09/2023 10:53, Simon Peyton Jones wrote:
Dear GHC SC
To avoid derailing the debate about -Wsevere < https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, and HasField redesign < https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, I'm starting a new (email for now) thread about stability.
I have tried to articulate what I believe is an evolving consensus in this document < https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47Zulga... .
If we converge, we'll turn that into a proper PR for the GHC proposal process, although it has wider implications than just GHC proposals and we should share with a broader audience. But let's start with the steering committee.
Any views? You all have edit rights.
I think that the draft covers Moritz's and Julian's goals, at least that was my intention. I have pasted Moritz's last email below, for context.
Simon
========= Moritz's last email ============
Now, this is derailing the original discussion a bit, and I'm not sure how far we want to take this. But, regarding @Simon Marlow <mailto:marlowsd@gmail.com>'s comment
This is one cultural aspect of our community I'd like to shift: the expectation that it's OK to make breaking changes as long as you warn about them or go through a migration cycle. It just isn't! (and I speak as someone who used to make lots of changes, I'm now fully repentant!). That's not to say that we shouldn't ever change anything, but when considering the cost/benefit tradeoff adding a migration cycle doesn't reduce the cost, it just defers it.
I actually read this as we should stop having breaking changes to begin with. And _if_ we do have breaking changes, that deprecation does not change the need to actually change code (cost). As outlined in my reply to that, and @Richard Eisenberg <mailto:lists@richarde.dev>'s observation, it "smears" the cost. The--to me--_much_ bigger implication of deprecation cycles is that we _inform_ our _customers_ about upcoming changes _early_, instead of _after the fact_. We also give them ample time to react. Being by changing their code, or raising their concerns. Would the Simplified Subsumptions / Deep Subsumptions change have looked differently? As such I see deprecation cycles as orthogonal to the question if we should have breaking changes to begin with.
Thus I believe the following:
- Do have a deprecation cycle if possible. - Do not treat a deprecation cycle as an excuse. Costs are deferred but are as large as ever.
should be upgraded to: - Preferably _no_ breaking changes. - If breaking changes, then with a deprecation cycle, unless technically infeasible. - An understanding that any breaking change incurs significant costs.
Ocaml recently added multicore support, and they put tremendous effort into making sure it keeps backwards compatibility: https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md <https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md>
PS: we should also agree that a "stable" extension should not require dependencies on ghc-experimental. To become stable, any library support for an extension must move into `base`.
This seems like a good idea, however I still remain that _experimental_ features should not be on-by-default in a stable compiler. Yes, ideally I'd not even see them in a stable compiler, but I know this view is contentious. The use of `ghc-experimental` should therefore be guarded by `--std=experimental` as Julian suggested. That is a loud opt-in to experimental features.
-- Adam Gundry, Haskell Consultant Well-Typed LLP, https://www.well-typed.com/
Registered in England & Wales, OC335890 27 Old Gloucester Street, London WC1N 3AX, England
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
Dear Adam, Thank you for your thoughtful feedback. I understand your reservations, and it's essential that we continue to have these discussions to ensure we're making the best decisions for the project and our community. Let me address each of your points in turn: - Cognitive Overhead for Users: I understand the concern about cognitive overhead due to the inability to remove complexity. However, our primary intention is to ensure a gradual transition for our users rather than abrupt shifts. Introducing changes via deprecation cycles allows users to adjust to modifications over time, reducing the immediate cognitive load. It's a balance between stability and simplicity, and I believe this approach allows us still to reduce complexity. - Maintenance Burden in the Compiler: Maintaining backward compatibility does indeed introduce some overhead. Still, it also encourages a more disciplined and considered approach to changes. With our deprecation cycles in place, it's not that we never remove complexity; rather, we do it in a way that provides ample time for adjustments. This benefits both the development team and the community. - Risk of Local Optimum: This is a valid concern. However, deprecation cycles don't mean we're averse to major changes. It means we introduce them responsibly. When we believe a superior design is possible, we can start a deprecation process to transition towards it. The flexibility and duration of our deprecation cycles can be tailored depending on the severity of the breaking change. - Discouraging Volunteer Contributors: I understand that lengthy approval processes can be off-putting. But it's crucial to note that a rigorous process ensures the consistency and reliability of our project. We always welcome and value contributions. Moreover, I believe this stability policy will provide us with clear guardrails on how changes can be contributed. I will not disagree on the costs. I do believe though that the costs for _breaking_ changes in the compiler ought to be borne by the people making the change, instead of those who use the compiler (and may not even benefit of those changes that caused breakage). I also see the team maintaining GHC as the one to enforce this; they are the ones who cut the releases. The fact that we may have breaking changes due to _bugs_ is covered explicitly in the stability policy document. With my CLC hat on, I have been focusing on the same stability guidelines as well (if it breaks existing code, I have been against those changes without deprecation policies). The issues with the template-haskell, and ghc library are noted. For the ghc library the question will remain if we intent to provide a stable api to the compiler or not. I believe many tools would like to have one, and if we relegate anything unstable to ghc-experimental this might be achieved. For template-haskell this is a bigger concern. Maybe we can collectively come up with a solution that would allow us to provide a more insulated template haskell interface from the compiler. However for template-haskell we might also need to look at what exactly caused those breaking changes in the past. What this document outlines (in my understanding) is that any experimental feature development can _only_ be visible behind --std=experimental, and the dependency of ghc-experimental. Unless those are given, the compiler should accept existing programs. This should allow us enough room to innovate (everyone is always free to opt-in to bleeding edge features with --std=experimental). I also believe that most of what we have today will need to be treated as non-experimental simply because we did not have that mechanism before. We don't want to break existing programs as much as possible, thus relegating existing features into --std=experimental (except for some fairly clear ones: e.g. Dependent Haskell, and Linear Types?) is not really possible. What we can however do is start deprecation phases for a few versions, moving features we consider highly experimental (or maybe even bad) into `--std=experimental`. Just by having deprecation phases and given the ecosystem enough time to adjust (and provide feedback) we might come to different conclusions. As I've also outlined in the document, _if_ GHC was trivially swappable, companies like IOG would _love_ to try new compilers and report back bugs and regressions. As it is today, we can't. Making a large live codebase compatible with 9.8 is a multiple weeks effort. Experimenting with nightlies is technically impossible. _If_ I could setup the built of our software trivial with ghc nightlies, I'd be _happy_ to build the infrastructure out it to provide performance regressions (compilation, runtime, ...) for our codebase and provide the feedback to the GHC team; however I can't. And thus I'm stuck patching and fixing 8.10, and 9.2 today. 9.6 maybe soon, but likely at the point in time where 9.6 is not going to see any further releases, so I can spare trying to even forward port my patches to HEAD. Not that I could even test them with head properly, as our source is not accepted by HEAD. Thus I end up writing patches against old stale branches. This to me is a fairly big discouragement from contributing to GHC. Best, Moritz On Mon, 25 Sept 2023 at 15:17, Adam Gundry <adam@well-typed.com> wrote:
I'm afraid that I'm somewhat sceptical of this approach.
A strong stability guarantee is certainly a valuable goal, but it also comes with costs, which I'd like to see more clearly articulated. Some of them include:
* Cognitive overhead for users, because of the inability to remove complexity from the design.
* Increasing maintenance burden in the compiler, because of the additional work needed to implement new features and the inability to remove complexity from the implementation.
* A risk of getting stuck in a local optimum, because moving to a better design would entail breaking changes.
* Discouraging volunteer contributors, who are much less likely to work on a potentially beneficial change if the process for getting it approved is too onerous. (I'm worried we're already reaching that point due to the increasing burden of well-intentioned processes.)
Ultimately every proposed change has a cost-benefit trade-off, with risk of breakage being one of the costs. We need to consciously evaluate that trade-off on a case-by-case basis. Almost all changes might break something (e.g. by regressing performance, or for Hyrum's Law reasons), so there needs to be a proportionate assessment of how likely each change is to be damaging in practice, bearing in mind that such an assessment is itself costly and limited in scope.
It seems to me that the GHC team have taken on board lessons regarding stability of the language, and the extension system already gives quite a lot of flexibility to evolve the language in a backwards-compatible way. In my experience, the key stability problems preventing upgrades to recent GHC releases are:
* The cascading effect of breaking changes in one library causing the need to upgrade libraries which depend upon it. This is primarily under the control of the CLC and library maintainers, however, not the GHC team. It would help if base was minimal and reinstallable, but that isn't a total solution either, because you'd still have to worry about packages depending on template-haskell or the ghc package itself.
* Performance regressions or critical bugs. These tend to be a significant obstacle to upgrading for smaller commercial users. But spending more of our limited resources on stability of the language means fewer resources for resolving these issues.
There's surely more we can do here, but let's be careful not to pay too many costs to achieve stability of the *language* alone, when stability of the *libraries* and *implementation* are both more important and harder to fix.
Adam
On 22/09/2023 10:53, Simon Peyton Jones wrote:
Dear GHC SC
To avoid derailing the debate about -Wsevere < https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, and HasField redesign < https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, I'm starting a new (email for now) thread about stability.
I have tried to articulate what I believe is an evolving consensus in this document < https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47Zulga... .
If we converge, we'll turn that into a proper PR for the GHC proposal process, although it has wider implications than just GHC proposals and we should share with a broader audience. But let's start with the steering committee.
Any views? You all have edit rights.
I think that the draft covers Moritz's and Julian's goals, at least that was my intention. I have pasted Moritz's last email below, for context.
Simon
========= Moritz's last email ============
Now, this is derailing the original discussion a bit, and I'm not sure how far we want to take this. But, regarding @Simon Marlow <mailto:marlowsd@gmail.com>'s comment
This is one cultural aspect of our community I'd like to shift: the expectation that it's OK to make breaking changes as long as you warn about them or go through a migration cycle. It just isn't! (and I speak as someone who used to make lots of changes, I'm now fully repentant!). That's not to say that we shouldn't ever change anything, but when considering the cost/benefit tradeoff adding a migration cycle doesn't reduce the cost, it just defers it.
I actually read this as we should stop having breaking changes to begin with. And _if_ we do have breaking changes, that deprecation does not change the need to actually change code (cost). As outlined in my reply to that, and @Richard Eisenberg <mailto:lists@richarde.dev>'s observation, it "smears" the cost. The--to me--_much_ bigger implication of deprecation cycles is that we _inform_ our _customers_ about upcoming changes _early_, instead of _after the fact_. We also give them ample time to react. Being by changing their code, or raising their concerns. Would the Simplified Subsumptions / Deep Subsumptions change have looked differently? As such I see deprecation cycles as orthogonal to the question if we should have breaking changes to begin with.
Thus I believe the following:
- Do have a deprecation cycle if possible. - Do not treat a deprecation cycle as an excuse. Costs are deferred but are as large as ever.
should be upgraded to: - Preferably _no_ breaking changes. - If breaking changes, then with a deprecation cycle, unless technically infeasible. - An understanding that any breaking change incurs significant costs.
Ocaml recently added multicore support, and they put tremendous effort into making sure it keeps backwards compatibility: https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md <https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md>
PS: we should also agree that a "stable" extension should not require dependencies on ghc-experimental. To become stable, any library support for an extension must move into `base`.
This seems like a good idea, however I still remain that _experimental_ features should not be on-by-default in a stable compiler. Yes, ideally I'd not even see them in a stable compiler, but I know this view is contentious. The use of `ghc-experimental` should therefore be guarded by `--std=experimental` as Julian suggested. That is a loud opt-in to experimental features.
-- Adam Gundry, Haskell Consultant Well-Typed LLP, https://www.well-typed.com/
Registered in England & Wales, OC335890 27 Old Gloucester Street, London WC1N 3AX, England
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
it's essential that we continue to have these discussions to ensure we're making the best decisions for the project and our community.
Yes exactly! Its tricky and nuanced; hence trying to articulate something in a concrete doc, so we are all on the same page (literally!). However, deprecation cycles don't mean we're averse to major changes. It
means we introduce them responsibly. When we believe a superior design is possible, we can start a deprecation process to transition towards it.
I have tried to make this explicit in Section 4. See what you think. I think there are three phases 1. Agree this document. Is it what we want. 2. Categorise extensions into stable/experimental, and identify experimental language features. 3. Implement --std=experimental (Section 6). (1) is what we are doing now. (2) will be some work, done by us. (3) is a larger task: it will require significant work to implement, and may impose unwelcome churn of its own. But that should not stop us doing (1) and (2). Simon - On Wed, 27 Sept 2023 at 10:20, Moritz Angermann <moritz.angermann@gmail.com> wrote:
Dear Adam,
Thank you for your thoughtful feedback. I understand your reservations, and it's essential that we continue to have these discussions to ensure we're making the best decisions for the project and our community. Let me address each of your points in turn: - Cognitive Overhead for Users: I understand the concern about cognitive overhead due to the inability to remove complexity. However, our primary intention is to ensure a gradual transition for our users rather than abrupt shifts. Introducing changes via deprecation cycles allows users to adjust to modifications over time, reducing the immediate cognitive load. It's a balance between stability and simplicity, and I believe this approach allows us still to reduce complexity.
- Maintenance Burden in the Compiler: Maintaining backward compatibility does indeed introduce some overhead. Still, it also encourages a more disciplined and considered approach to changes. With our deprecation cycles in place, it's not that we never remove complexity; rather, we do it in a way that provides ample time for adjustments. This benefits both the development team and the community.
- Risk of Local Optimum: This is a valid concern. However, deprecation cycles don't mean we're averse to major changes. It means we introduce them responsibly. When we believe a superior design is possible, we can start a deprecation process to transition towards it. The flexibility and duration of our deprecation cycles can be tailored depending on the severity of the breaking change.
- Discouraging Volunteer Contributors: I understand that lengthy approval processes can be off-putting. But it's crucial to note that a rigorous process ensures the consistency and reliability of our project. We always welcome and value contributions. Moreover, I believe this stability policy will provide us with clear guardrails on how changes can be contributed.
I will not disagree on the costs. I do believe though that the costs for _breaking_ changes in the compiler ought to be borne by the people making the change, instead of those who use the compiler (and may not even benefit of those changes that caused breakage). I also see the team maintaining GHC as the one to enforce this; they are the ones who cut the releases. The fact that we may have breaking changes due to _bugs_ is covered explicitly in the stability policy document.
With my CLC hat on, I have been focusing on the same stability guidelines as well (if it breaks existing code, I have been against those changes without deprecation policies). The issues with the template-haskell, and ghc library are noted. For the ghc library the question will remain if we intent to provide a stable api to the compiler or not. I believe many tools would like to have one, and if we relegate anything unstable to ghc-experimental this might be achieved. For template-haskell this is a bigger concern. Maybe we can collectively come up with a solution that would allow us to provide a more insulated template haskell interface from the compiler.
However for template-haskell we might also need to look at what exactly caused those breaking changes in the past.
What this document outlines (in my understanding) is that any experimental feature development can _only_ be visible behind --std=experimental, and the dependency of ghc-experimental. Unless those are given, the compiler should accept existing programs. This should allow us enough room to innovate (everyone is always free to opt-in to bleeding edge features with --std=experimental). I also believe that most of what we have today will need to be treated as non-experimental simply because we did not have that mechanism before. We don't want to break existing programs as much as possible, thus relegating existing features into --std=experimental (except for some fairly clear ones: e.g. Dependent Haskell, and Linear Types?) is not really possible. What we can however do is start deprecation phases for a few versions, moving features we consider highly experimental (or maybe even bad) into `--std=experimental`. Just by having deprecation phases and given the ecosystem enough time to adjust (and provide feedback) we might come to different conclusions.
As I've also outlined in the document, _if_ GHC was trivially swappable, companies like IOG would _love_ to try new compilers and report back bugs and regressions. As it is today, we can't. Making a large live codebase compatible with 9.8 is a multiple weeks effort. Experimenting with nightlies is technically impossible. _If_ I could setup the built of our software trivial with ghc nightlies, I'd be _happy_ to build the infrastructure out it to provide performance regressions (compilation, runtime, ...) for our codebase and provide the feedback to the GHC team; however I can't. And thus I'm stuck patching and fixing 8.10, and 9.2 today. 9.6 maybe soon, but likely at the point in time where 9.6 is not going to see any further releases, so I can spare trying to even forward port my patches to HEAD. Not that I could even test them with head properly, as our source is not accepted by HEAD. Thus I end up writing patches against old stale branches. This to me is a fairly big discouragement from contributing to GHC.
Best, Moritz
On Mon, 25 Sept 2023 at 15:17, Adam Gundry <adam@well-typed.com> wrote:
I'm afraid that I'm somewhat sceptical of this approach.
A strong stability guarantee is certainly a valuable goal, but it also comes with costs, which I'd like to see more clearly articulated. Some of them include:
* Cognitive overhead for users, because of the inability to remove complexity from the design.
* Increasing maintenance burden in the compiler, because of the additional work needed to implement new features and the inability to remove complexity from the implementation.
* A risk of getting stuck in a local optimum, because moving to a better design would entail breaking changes.
* Discouraging volunteer contributors, who are much less likely to work on a potentially beneficial change if the process for getting it approved is too onerous. (I'm worried we're already reaching that point due to the increasing burden of well-intentioned processes.)
Ultimately every proposed change has a cost-benefit trade-off, with risk of breakage being one of the costs. We need to consciously evaluate that trade-off on a case-by-case basis. Almost all changes might break something (e.g. by regressing performance, or for Hyrum's Law reasons), so there needs to be a proportionate assessment of how likely each change is to be damaging in practice, bearing in mind that such an assessment is itself costly and limited in scope.
It seems to me that the GHC team have taken on board lessons regarding stability of the language, and the extension system already gives quite a lot of flexibility to evolve the language in a backwards-compatible way. In my experience, the key stability problems preventing upgrades to recent GHC releases are:
* The cascading effect of breaking changes in one library causing the need to upgrade libraries which depend upon it. This is primarily under the control of the CLC and library maintainers, however, not the GHC team. It would help if base was minimal and reinstallable, but that isn't a total solution either, because you'd still have to worry about packages depending on template-haskell or the ghc package itself.
* Performance regressions or critical bugs. These tend to be a significant obstacle to upgrading for smaller commercial users. But spending more of our limited resources on stability of the language means fewer resources for resolving these issues.
There's surely more we can do here, but let's be careful not to pay too many costs to achieve stability of the *language* alone, when stability of the *libraries* and *implementation* are both more important and harder to fix.
Adam
On 22/09/2023 10:53, Simon Peyton Jones wrote:
Dear GHC SC
To avoid derailing the debate about -Wsevere < https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, and HasField redesign < https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, I'm starting a new (email for now) thread about stability.
I have tried to articulate what I believe is an evolving consensus in this document < https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47Zulga... .
If we converge, we'll turn that into a proper PR for the GHC proposal process, although it has wider implications than just GHC proposals and we should share with a broader audience. But let's start with the steering committee.
Any views? You all have edit rights.
I think that the draft covers Moritz's and Julian's goals, at least that was my intention. I have pasted Moritz's last email below, for context.
Simon
========= Moritz's last email ============
Now, this is derailing the original discussion a bit, and I'm not sure how far we want to take this. But, regarding @Simon Marlow <mailto:marlowsd@gmail.com>'s comment
This is one cultural aspect of our community I'd like to shift: the expectation that it's OK to make breaking changes as long as you warn about them or go through a migration cycle. It just isn't! (and I speak as someone who used to make lots of changes, I'm now fully repentant!). That's not to say that we shouldn't ever change anything, but when considering the cost/benefit tradeoff adding a migration cycle doesn't reduce the cost, it just defers it.
I actually read this as we should stop having breaking changes to begin with. And _if_ we do have breaking changes, that deprecation does not change the need to actually change code (cost). As outlined in my reply to that, and @Richard Eisenberg <mailto:lists@richarde.dev>'s observation, it "smears" the cost. The--to me--_much_ bigger implication of deprecation cycles is that we _inform_ our _customers_ about upcoming changes _early_, instead of _after the fact_. We also give them ample time to react. Being by changing their code, or raising their concerns. Would the Simplified Subsumptions / Deep Subsumptions change have looked differently? As such I see deprecation cycles as orthogonal to the question if we should have breaking changes to begin with.
Thus I believe the following:
- Do have a deprecation cycle if possible. - Do not treat a deprecation cycle as an excuse. Costs are deferred but are as large as ever.
should be upgraded to: - Preferably _no_ breaking changes. - If breaking changes, then with a deprecation cycle, unless technically infeasible. - An understanding that any breaking change incurs significant costs.
Ocaml recently added multicore support, and they put tremendous effort into making sure it keeps backwards compatibility: https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md <https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md>
PS: we should also agree that a "stable" extension should not require dependencies on ghc-experimental. To become stable, any library support for an extension must move into `base`.
This seems like a good idea, however I still remain that _experimental_ features should not be on-by-default in a stable compiler. Yes, ideally I'd not even see them in a stable compiler, but I know this view is contentious. The use of `ghc-experimental` should therefore be guarded by `--std=experimental` as Julian suggested. That is a loud opt-in to experimental features.
-- Adam Gundry, Haskell Consultant Well-Typed LLP, https://www.well-typed.com/
Registered in England & Wales, OC335890 27 Old Gloucester Street, London WC1N 3AX, England
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
I think we are moving in the right direction! I do see however the tension rising on (2). And without being clear about (2), I don’t think we can properly agree on (1). We can agree on (1) in principle, but we need to clarify what we consider unstable/experimental, as a precondition to have finale agreement on (1). Otherwise people might agree to (1), only to be surprised by (2). For (3), I’d be happy to try to get my employer to provide resources for the implementation of —std=experimental. Thusly I believe we should start to build a list of features we consider sufficiently experimental that they should preclude an existing Haskell program from being considered stable. This list for me contains so far: - Linear Types - Dependent Haskell Adam pointed out experimental backend and non-tire-1 platforms. I tend to agree with this, but see this distinctly separate from the language stability (outside of backend specific language extensions, e.g. JSFFI). Platforms/backends may be experimental but those are (safe for specific lang exts) orthogonal to the Haskell code the compiler accepts. Should we have a document (or better spreadsheet?) with a bullet point for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature. Best, Moritz On Wed, 27 Sep 2023 at 10:35 PM, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
it's essential that we continue to have these discussions to ensure we're
making the best decisions for the project and our community.
Yes exactly! Its tricky and nuanced; hence trying to articulate something in a concrete doc, so we are all on the same page (literally!).
However, deprecation cycles don't mean we're averse to major changes. It
means we introduce them responsibly. When we believe a superior design is possible, we can start a deprecation process to transition towards it.
I have tried to make this explicit in Section 4. See what you think.
I think there are three phases
1. Agree this document. Is it what we want. 2. Categorise extensions into stable/experimental, and identify experimental language features. 3. Implement --std=experimental (Section 6).
(1) is what we are doing now. (2) will be some work, done by us. (3) is a larger task: it will require significant work to implement, and may impose unwelcome churn of its own. But that should not stop us doing (1) and (2).
Simon
-
On Wed, 27 Sept 2023 at 10:20, Moritz Angermann < moritz.angermann@gmail.com> wrote:
Dear Adam,
Thank you for your thoughtful feedback. I understand your reservations, and it's essential that we continue to have these discussions to ensure we're making the best decisions for the project and our community. Let me address each of your points in turn: - Cognitive Overhead for Users: I understand the concern about cognitive overhead due to the inability to remove complexity. However, our primary intention is to ensure a gradual transition for our users rather than abrupt shifts. Introducing changes via deprecation cycles allows users to adjust to modifications over time, reducing the immediate cognitive load. It's a balance between stability and simplicity, and I believe this approach allows us still to reduce complexity.
- Maintenance Burden in the Compiler: Maintaining backward compatibility does indeed introduce some overhead. Still, it also encourages a more disciplined and considered approach to changes. With our deprecation cycles in place, it's not that we never remove complexity; rather, we do it in a way that provides ample time for adjustments. This benefits both the development team and the community.
- Risk of Local Optimum: This is a valid concern. However, deprecation cycles don't mean we're averse to major changes. It means we introduce them responsibly. When we believe a superior design is possible, we can start a deprecation process to transition towards it. The flexibility and duration of our deprecation cycles can be tailored depending on the severity of the breaking change.
- Discouraging Volunteer Contributors: I understand that lengthy approval processes can be off-putting. But it's crucial to note that a rigorous process ensures the consistency and reliability of our project. We always welcome and value contributions. Moreover, I believe this stability policy will provide us with clear guardrails on how changes can be contributed.
I will not disagree on the costs. I do believe though that the costs for _breaking_ changes in the compiler ought to be borne by the people making the change, instead of those who use the compiler (and may not even benefit of those changes that caused breakage). I also see the team maintaining GHC as the one to enforce this; they are the ones who cut the releases. The fact that we may have breaking changes due to _bugs_ is covered explicitly in the stability policy document.
With my CLC hat on, I have been focusing on the same stability guidelines as well (if it breaks existing code, I have been against those changes without deprecation policies). The issues with the template-haskell, and ghc library are noted. For the ghc library the question will remain if we intent to provide a stable api to the compiler or not. I believe many tools would like to have one, and if we relegate anything unstable to ghc-experimental this might be achieved. For template-haskell this is a bigger concern. Maybe we can collectively come up with a solution that would allow us to provide a more insulated template haskell interface from the compiler.
However for template-haskell we might also need to look at what exactly caused those breaking changes in the past.
What this document outlines (in my understanding) is that any experimental feature development can _only_ be visible behind --std=experimental, and the dependency of ghc-experimental. Unless those are given, the compiler should accept existing programs. This should allow us enough room to innovate (everyone is always free to opt-in to bleeding edge features with --std=experimental). I also believe that most of what we have today will need to be treated as non-experimental simply because we did not have that mechanism before. We don't want to break existing programs as much as possible, thus relegating existing features into --std=experimental (except for some fairly clear ones: e.g. Dependent Haskell, and Linear Types?) is not really possible. What we can however do is start deprecation phases for a few versions, moving features we consider highly experimental (or maybe even bad) into `--std=experimental`. Just by having deprecation phases and given the ecosystem enough time to adjust (and provide feedback) we might come to different conclusions.
As I've also outlined in the document, _if_ GHC was trivially swappable, companies like IOG would _love_ to try new compilers and report back bugs and regressions. As it is today, we can't. Making a large live codebase compatible with 9.8 is a multiple weeks effort. Experimenting with nightlies is technically impossible. _If_ I could setup the built of our software trivial with ghc nightlies, I'd be _happy_ to build the infrastructure out it to provide performance regressions (compilation, runtime, ...) for our codebase and provide the feedback to the GHC team; however I can't. And thus I'm stuck patching and fixing 8.10, and 9.2 today. 9.6 maybe soon, but likely at the point in time where 9.6 is not going to see any further releases, so I can spare trying to even forward port my patches to HEAD. Not that I could even test them with head properly, as our source is not accepted by HEAD. Thus I end up writing patches against old stale branches. This to me is a fairly big discouragement from contributing to GHC.
Best, Moritz
On Mon, 25 Sept 2023 at 15:17, Adam Gundry <adam@well-typed.com> wrote:
I'm afraid that I'm somewhat sceptical of this approach.
A strong stability guarantee is certainly a valuable goal, but it also comes with costs, which I'd like to see more clearly articulated. Some of them include:
* Cognitive overhead for users, because of the inability to remove complexity from the design.
* Increasing maintenance burden in the compiler, because of the additional work needed to implement new features and the inability to remove complexity from the implementation.
* A risk of getting stuck in a local optimum, because moving to a better design would entail breaking changes.
* Discouraging volunteer contributors, who are much less likely to work on a potentially beneficial change if the process for getting it approved is too onerous. (I'm worried we're already reaching that point due to the increasing burden of well-intentioned processes.)
Ultimately every proposed change has a cost-benefit trade-off, with risk of breakage being one of the costs. We need to consciously evaluate that trade-off on a case-by-case basis. Almost all changes might break something (e.g. by regressing performance, or for Hyrum's Law reasons), so there needs to be a proportionate assessment of how likely each change is to be damaging in practice, bearing in mind that such an assessment is itself costly and limited in scope.
It seems to me that the GHC team have taken on board lessons regarding stability of the language, and the extension system already gives quite a lot of flexibility to evolve the language in a backwards-compatible way. In my experience, the key stability problems preventing upgrades to recent GHC releases are:
* The cascading effect of breaking changes in one library causing the need to upgrade libraries which depend upon it. This is primarily under the control of the CLC and library maintainers, however, not the GHC team. It would help if base was minimal and reinstallable, but that isn't a total solution either, because you'd still have to worry about packages depending on template-haskell or the ghc package itself.
* Performance regressions or critical bugs. These tend to be a significant obstacle to upgrading for smaller commercial users. But spending more of our limited resources on stability of the language means fewer resources for resolving these issues.
There's surely more we can do here, but let's be careful not to pay too many costs to achieve stability of the *language* alone, when stability of the *libraries* and *implementation* are both more important and harder to fix.
Adam
On 22/09/2023 10:53, Simon Peyton Jones wrote:
Dear GHC SC
To avoid derailing the debate about -Wsevere < https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, and HasField redesign < https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, I'm starting a new (email for now) thread about stability.
I have tried to articulate what I believe is an evolving consensus in this document < https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47Zulga... .
If we converge, we'll turn that into a proper PR for the GHC proposal process, although it has wider implications than just GHC proposals and we should share with a broader audience. But let's start with the steering committee.
Any views? You all have edit rights.
I think that the draft covers Moritz's and Julian's goals, at least that was my intention. I have pasted Moritz's last email below, for context.
Simon
========= Moritz's last email ============
Now, this is derailing the original discussion a bit, and I'm not sure how far we want to take this. But, regarding @Simon Marlow <mailto:marlowsd@gmail.com>'s comment
This is one cultural aspect of our community I'd like to shift: the expectation that it's OK to make breaking changes as long as you warn about them or go through a migration cycle. It just isn't! (and I speak as someone who used to make lots of changes, I'm now fully repentant!). That's not to say that we shouldn't ever change anything, but when considering the cost/benefit tradeoff adding a migration cycle doesn't reduce the cost, it just defers it.
I actually read this as we should stop having breaking changes to begin with. And _if_ we do have breaking changes, that deprecation does not change the need to actually change code (cost). As outlined in my reply to that, and @Richard Eisenberg <mailto:lists@richarde.dev>'s observation, it "smears" the cost. The--to me--_much_ bigger implication of deprecation cycles is that we _inform_ our _customers_ about upcoming changes _early_, instead of _after the fact_. We also give them ample time to react. Being by changing their code, or raising their concerns. Would the Simplified Subsumptions / Deep Subsumptions change have looked differently? As such I see deprecation cycles as orthogonal to the question if we should have breaking changes to begin with.
Thus I believe the following:
- Do have a deprecation cycle if possible. - Do not treat a deprecation cycle as an excuse. Costs are deferred but are as large as ever.
should be upgraded to: - Preferably _no_ breaking changes. - If breaking changes, then with a deprecation cycle, unless technically infeasible. - An understanding that any breaking change incurs significant costs.
Ocaml recently added multicore support, and they put tremendous effort into making sure it keeps backwards compatibility: https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md <https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md>
PS: we should also agree that a "stable" extension should not require dependencies on ghc-experimental. To become stable, any library support for an extension must move into `base`.
This seems like a good idea, however I still remain that _experimental_ features should not be on-by-default in a stable compiler. Yes, ideally I'd not even see them in a stable compiler, but I know this view is contentious. The use of `ghc-experimental` should therefore be guarded by `--std=experimental` as Julian suggested. That is a loud opt-in to experimental features.
-- Adam Gundry, Haskell Consultant Well-Typed LLP, https://www.well-typed.com/
Registered in England & Wales, OC335890 27 Old Gloucester Street, London WC1N 3AX, England <https://www.google.com/maps/search/27+Old+Gloucester+Street,+London+WC1N+3AX,+England?entry=gmail&source=g>
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
Should we have a document (or better spreadsheet?) with a bullet point for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
I think that would be a helpful way to "ground" the discussion a bit more. (The spreadsheet should also give a preliminary classification of extensions, at least into stable/experimental.) I'm running out of capacity to drive this debate, useful though it is. Does anyone else feel able to drive some of the legwork? So far this is all informal committee discussion. The next step would be a GHC Proposal inviting broader feedback from the community. I'm just hoping that by debugging it between ourselves we can side-step some unproductive discussions in that bigger context. I believe we need to take into account that we can’t end up classifying
most of todays Haskell programs unstable
There is a tension here. If we say something is "stable" then we have to be super-careful about changing it. (That's the whole point.) And yet if the feature (like INCOHERENT) is a flaky "you are on your own" unsafePerformIO-like feature, I am axious about tying ourselves into an inability to change the behaviour of corner cases. I'm not sure how to resolve this tension. Simon On Thu, 28 Sept 2023 at 02:20, Moritz Angermann <moritz.angermann@gmail.com> wrote:
I think we are moving in the right direction! I do see however the tension rising on (2). And without being clear about (2), I don’t think we can properly agree on (1). We can agree on (1) in principle, but we need to clarify what we consider unstable/experimental, as a precondition to have finale agreement on (1). Otherwise people might agree to (1), only to be surprised by (2). For (3), I’d be happy to try to get my employer to provide resources for the implementation of —std=experimental.
Thusly I believe we should start to build a list of features we consider sufficiently experimental that they should preclude an existing Haskell program from being considered stable. This list for me contains so far:
- Linear Types - Dependent Haskell
Adam pointed out experimental backend and non-tire-1 platforms. I tend to agree with this, but see this distinctly separate from the language stability (outside of backend specific language extensions, e.g. JSFFI).
Platforms/backends may be experimental but those are (safe for specific lang exts) orthogonal to the Haskell code the compiler accepts.
Should we have a document (or better spreadsheet?) with a bullet point for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
Best, Moritz
On Wed, 27 Sep 2023 at 10:35 PM, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
it's essential that we continue to have these discussions to ensure we're
making the best decisions for the project and our community.
Yes exactly! Its tricky and nuanced; hence trying to articulate something in a concrete doc, so we are all on the same page (literally!).
However, deprecation cycles don't mean we're averse to major changes. It
means we introduce them responsibly. When we believe a superior design is possible, we can start a deprecation process to transition towards it.
I have tried to make this explicit in Section 4. See what you think.
I think there are three phases
1. Agree this document. Is it what we want. 2. Categorise extensions into stable/experimental, and identify experimental language features. 3. Implement --std=experimental (Section 6).
(1) is what we are doing now. (2) will be some work, done by us. (3) is a larger task: it will require significant work to implement, and may impose unwelcome churn of its own. But that should not stop us doing (1) and (2).
Simon
-
On Wed, 27 Sept 2023 at 10:20, Moritz Angermann < moritz.angermann@gmail.com> wrote:
Dear Adam,
Thank you for your thoughtful feedback. I understand your reservations, and it's essential that we continue to have these discussions to ensure we're making the best decisions for the project and our community. Let me address each of your points in turn: - Cognitive Overhead for Users: I understand the concern about cognitive overhead due to the inability to remove complexity. However, our primary intention is to ensure a gradual transition for our users rather than abrupt shifts. Introducing changes via deprecation cycles allows users to adjust to modifications over time, reducing the immediate cognitive load. It's a balance between stability and simplicity, and I believe this approach allows us still to reduce complexity.
- Maintenance Burden in the Compiler: Maintaining backward compatibility does indeed introduce some overhead. Still, it also encourages a more disciplined and considered approach to changes. With our deprecation cycles in place, it's not that we never remove complexity; rather, we do it in a way that provides ample time for adjustments. This benefits both the development team and the community.
- Risk of Local Optimum: This is a valid concern. However, deprecation cycles don't mean we're averse to major changes. It means we introduce them responsibly. When we believe a superior design is possible, we can start a deprecation process to transition towards it. The flexibility and duration of our deprecation cycles can be tailored depending on the severity of the breaking change.
- Discouraging Volunteer Contributors: I understand that lengthy approval processes can be off-putting. But it's crucial to note that a rigorous process ensures the consistency and reliability of our project. We always welcome and value contributions. Moreover, I believe this stability policy will provide us with clear guardrails on how changes can be contributed.
I will not disagree on the costs. I do believe though that the costs for _breaking_ changes in the compiler ought to be borne by the people making the change, instead of those who use the compiler (and may not even benefit of those changes that caused breakage). I also see the team maintaining GHC as the one to enforce this; they are the ones who cut the releases. The fact that we may have breaking changes due to _bugs_ is covered explicitly in the stability policy document.
With my CLC hat on, I have been focusing on the same stability guidelines as well (if it breaks existing code, I have been against those changes without deprecation policies). The issues with the template-haskell, and ghc library are noted. For the ghc library the question will remain if we intent to provide a stable api to the compiler or not. I believe many tools would like to have one, and if we relegate anything unstable to ghc-experimental this might be achieved. For template-haskell this is a bigger concern. Maybe we can collectively come up with a solution that would allow us to provide a more insulated template haskell interface from the compiler.
However for template-haskell we might also need to look at what exactly caused those breaking changes in the past.
What this document outlines (in my understanding) is that any experimental feature development can _only_ be visible behind --std=experimental, and the dependency of ghc-experimental. Unless those are given, the compiler should accept existing programs. This should allow us enough room to innovate (everyone is always free to opt-in to bleeding edge features with --std=experimental). I also believe that most of what we have today will need to be treated as non-experimental simply because we did not have that mechanism before. We don't want to break existing programs as much as possible, thus relegating existing features into --std=experimental (except for some fairly clear ones: e.g. Dependent Haskell, and Linear Types?) is not really possible. What we can however do is start deprecation phases for a few versions, moving features we consider highly experimental (or maybe even bad) into `--std=experimental`. Just by having deprecation phases and given the ecosystem enough time to adjust (and provide feedback) we might come to different conclusions.
As I've also outlined in the document, _if_ GHC was trivially swappable, companies like IOG would _love_ to try new compilers and report back bugs and regressions. As it is today, we can't. Making a large live codebase compatible with 9.8 is a multiple weeks effort. Experimenting with nightlies is technically impossible. _If_ I could setup the built of our software trivial with ghc nightlies, I'd be _happy_ to build the infrastructure out it to provide performance regressions (compilation, runtime, ...) for our codebase and provide the feedback to the GHC team; however I can't. And thus I'm stuck patching and fixing 8.10, and 9.2 today. 9.6 maybe soon, but likely at the point in time where 9.6 is not going to see any further releases, so I can spare trying to even forward port my patches to HEAD. Not that I could even test them with head properly, as our source is not accepted by HEAD. Thus I end up writing patches against old stale branches. This to me is a fairly big discouragement from contributing to GHC.
Best, Moritz
On Mon, 25 Sept 2023 at 15:17, Adam Gundry <adam@well-typed.com> wrote:
I'm afraid that I'm somewhat sceptical of this approach.
A strong stability guarantee is certainly a valuable goal, but it also comes with costs, which I'd like to see more clearly articulated. Some of them include:
* Cognitive overhead for users, because of the inability to remove complexity from the design.
* Increasing maintenance burden in the compiler, because of the additional work needed to implement new features and the inability to remove complexity from the implementation.
* A risk of getting stuck in a local optimum, because moving to a better design would entail breaking changes.
* Discouraging volunteer contributors, who are much less likely to work on a potentially beneficial change if the process for getting it approved is too onerous. (I'm worried we're already reaching that point due to the increasing burden of well-intentioned processes.)
Ultimately every proposed change has a cost-benefit trade-off, with risk of breakage being one of the costs. We need to consciously evaluate that trade-off on a case-by-case basis. Almost all changes might break something (e.g. by regressing performance, or for Hyrum's Law reasons), so there needs to be a proportionate assessment of how likely each change is to be damaging in practice, bearing in mind that such an assessment is itself costly and limited in scope.
It seems to me that the GHC team have taken on board lessons regarding stability of the language, and the extension system already gives quite a lot of flexibility to evolve the language in a backwards-compatible way. In my experience, the key stability problems preventing upgrades to recent GHC releases are:
* The cascading effect of breaking changes in one library causing the need to upgrade libraries which depend upon it. This is primarily under the control of the CLC and library maintainers, however, not the GHC team. It would help if base was minimal and reinstallable, but that isn't a total solution either, because you'd still have to worry about packages depending on template-haskell or the ghc package itself.
* Performance regressions or critical bugs. These tend to be a significant obstacle to upgrading for smaller commercial users. But spending more of our limited resources on stability of the language means fewer resources for resolving these issues.
There's surely more we can do here, but let's be careful not to pay too many costs to achieve stability of the *language* alone, when stability of the *libraries* and *implementation* are both more important and harder to fix.
Adam
On 22/09/2023 10:53, Simon Peyton Jones wrote:
Dear GHC SC
To avoid derailing the debate about -Wsevere < https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, and HasField redesign < https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, I'm starting a new (email for now) thread about stability.
I have tried to articulate what I believe is an evolving consensus in this document < https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47Zulga... .
If we converge, we'll turn that into a proper PR for the GHC proposal process, although it has wider implications than just GHC proposals and we should share with a broader audience. But let's start with the steering committee.
Any views? You all have edit rights.
I think that the draft covers Moritz's and Julian's goals, at least that was my intention. I have pasted Moritz's last email below, for context.
Simon
========= Moritz's last email ============
Now, this is derailing the original discussion a bit, and I'm not sure how far we want to take this. But, regarding @Simon Marlow <mailto:marlowsd@gmail.com>'s comment
This is one cultural aspect of our community I'd like to shift: the expectation that it's OK to make breaking changes as long as you warn about them or go through a migration cycle. It just isn't! (and I speak as someone who used to make lots of changes, I'm now fully repentant!). That's not to say that we shouldn't ever change anything, but when considering the cost/benefit tradeoff adding a migration cycle doesn't reduce the cost, it just defers it.
I actually read this as we should stop having breaking changes to begin with. And _if_ we do have breaking changes, that deprecation does not change the need to actually change code (cost). As outlined in my reply to that, and @Richard Eisenberg <mailto:lists@richarde.dev>'s observation, it "smears" the cost. The--to me--_much_ bigger implication of deprecation cycles is that we _inform_ our _customers_ about upcoming changes _early_, instead of _after the fact_. We also give them ample time to react. Being by changing their code, or raising their concerns. Would the Simplified Subsumptions / Deep Subsumptions change have looked differently? As such I see deprecation cycles as orthogonal to the question if we should have breaking changes to begin with.
Thus I believe the following:
- Do have a deprecation cycle if possible. - Do not treat a deprecation cycle as an excuse. Costs are deferred but are as large as ever.
should be upgraded to: - Preferably _no_ breaking changes. - If breaking changes, then with a deprecation cycle, unless technically infeasible. - An understanding that any breaking change incurs significant costs.
Ocaml recently added multicore support, and they put tremendous effort into making sure it keeps backwards compatibility: https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md <https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md>
PS: we should also agree that a "stable" extension should not require dependencies on ghc-experimental. To become stable, any library support for an extension must move into `base`.
This seems like a good idea, however I still remain that _experimental_ features should not be on-by-default in a stable compiler. Yes, ideally I'd not even see them in a stable compiler, but I know this view is contentious. The use of `ghc-experimental` should therefore be guarded by `--std=experimental` as Julian suggested. That is a loud opt-in to experimental features.
-- Adam Gundry, Haskell Consultant Well-Typed LLP, https://www.well-typed.com/
Registered in England & Wales, OC335890 27 Old Gloucester Street, London WC1N 3AX, England <https://www.google.com/maps/search/27+Old+Gloucester+Street,+London+WC1N+3AX,+England?entry=gmail&source=g>
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
Simon, Thank you for bringing us this far. I'd be happy to step up to drive this further. I will say that I do see the tension you see as well. And I do believe if we come to a conclusion on this stability policy that it will make GHC development more rigorous, which I think is a good thing for all of us, not just the consumers of the compiler. I think we need to stay mindful that we can still freely experiment on the --std=experimental (or however that flag ends up being named) side. I see this whole discussion as leading us towards the language research reactor side of GHC being primarily confined behind --std=experimental, and the stability seeking (commercial application?) on the other side. I do not yet see how we can end up with the inability to change. We will just have a clearer process for _breaking_ changes. This does absolutely not mean we have to end up in a local optimum, or that we can not change. We can! Unless someone speaks up who does _not_ want me to drive, this, I'm happy to start driving this discussion (including writing the proposals, starting next week). Best, Moritz On Thu, 28 Sept 2023 at 19:30, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Should we have a document (or better spreadsheet?) with a bullet point for
each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
I think that would be a helpful way to "ground" the discussion a bit more. (The spreadsheet should also give a preliminary classification of extensions, at least into stable/experimental.)
I'm running out of capacity to drive this debate, useful though it is. Does anyone else feel able to drive some of the legwork?
So far this is all informal committee discussion. The next step would be a GHC Proposal inviting broader feedback from the community. I'm just hoping that by debugging it between ourselves we can side-step some unproductive discussions in that bigger context.
I believe we need to take into account that we can’t end up classifying
most of todays Haskell programs unstable
There is a tension here. If we say something is "stable" then we have to be super-careful about changing it. (That's the whole point.) And yet if the feature (like INCOHERENT) is a flaky "you are on your own" unsafePerformIO-like feature, I am axious about tying ourselves into an inability to change the behaviour of corner cases. I'm not sure how to resolve this tension.
Simon
On Thu, 28 Sept 2023 at 02:20, Moritz Angermann < moritz.angermann@gmail.com> wrote:
I think we are moving in the right direction! I do see however the tension rising on (2). And without being clear about (2), I don’t think we can properly agree on (1). We can agree on (1) in principle, but we need to clarify what we consider unstable/experimental, as a precondition to have finale agreement on (1). Otherwise people might agree to (1), only to be surprised by (2). For (3), I’d be happy to try to get my employer to provide resources for the implementation of —std=experimental.
Thusly I believe we should start to build a list of features we consider sufficiently experimental that they should preclude an existing Haskell program from being considered stable. This list for me contains so far:
- Linear Types - Dependent Haskell
Adam pointed out experimental backend and non-tire-1 platforms. I tend to agree with this, but see this distinctly separate from the language stability (outside of backend specific language extensions, e.g. JSFFI).
Platforms/backends may be experimental but those are (safe for specific lang exts) orthogonal to the Haskell code the compiler accepts.
Should we have a document (or better spreadsheet?) with a bullet point for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
Best, Moritz
On Wed, 27 Sep 2023 at 10:35 PM, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
it's essential that we continue to have these discussions to ensure
we're making the best decisions for the project and our community.
Yes exactly! Its tricky and nuanced; hence trying to articulate something in a concrete doc, so we are all on the same page (literally!).
However, deprecation cycles don't mean we're averse to major changes. It
means we introduce them responsibly. When we believe a superior design is possible, we can start a deprecation process to transition towards it.
I have tried to make this explicit in Section 4. See what you think.
I think there are three phases
1. Agree this document. Is it what we want. 2. Categorise extensions into stable/experimental, and identify experimental language features. 3. Implement --std=experimental (Section 6).
(1) is what we are doing now. (2) will be some work, done by us. (3) is a larger task: it will require significant work to implement, and may impose unwelcome churn of its own. But that should not stop us doing (1) and (2).
Simon
-
On Wed, 27 Sept 2023 at 10:20, Moritz Angermann < moritz.angermann@gmail.com> wrote:
Dear Adam,
Thank you for your thoughtful feedback. I understand your reservations, and it's essential that we continue to have these discussions to ensure we're making the best decisions for the project and our community. Let me address each of your points in turn: - Cognitive Overhead for Users: I understand the concern about cognitive overhead due to the inability to remove complexity. However, our primary intention is to ensure a gradual transition for our users rather than abrupt shifts. Introducing changes via deprecation cycles allows users to adjust to modifications over time, reducing the immediate cognitive load. It's a balance between stability and simplicity, and I believe this approach allows us still to reduce complexity.
- Maintenance Burden in the Compiler: Maintaining backward compatibility does indeed introduce some overhead. Still, it also encourages a more disciplined and considered approach to changes. With our deprecation cycles in place, it's not that we never remove complexity; rather, we do it in a way that provides ample time for adjustments. This benefits both the development team and the community.
- Risk of Local Optimum: This is a valid concern. However, deprecation cycles don't mean we're averse to major changes. It means we introduce them responsibly. When we believe a superior design is possible, we can start a deprecation process to transition towards it. The flexibility and duration of our deprecation cycles can be tailored depending on the severity of the breaking change.
- Discouraging Volunteer Contributors: I understand that lengthy approval processes can be off-putting. But it's crucial to note that a rigorous process ensures the consistency and reliability of our project. We always welcome and value contributions. Moreover, I believe this stability policy will provide us with clear guardrails on how changes can be contributed.
I will not disagree on the costs. I do believe though that the costs for _breaking_ changes in the compiler ought to be borne by the people making the change, instead of those who use the compiler (and may not even benefit of those changes that caused breakage). I also see the team maintaining GHC as the one to enforce this; they are the ones who cut the releases. The fact that we may have breaking changes due to _bugs_ is covered explicitly in the stability policy document.
With my CLC hat on, I have been focusing on the same stability guidelines as well (if it breaks existing code, I have been against those changes without deprecation policies). The issues with the template-haskell, and ghc library are noted. For the ghc library the question will remain if we intent to provide a stable api to the compiler or not. I believe many tools would like to have one, and if we relegate anything unstable to ghc-experimental this might be achieved. For template-haskell this is a bigger concern. Maybe we can collectively come up with a solution that would allow us to provide a more insulated template haskell interface from the compiler.
However for template-haskell we might also need to look at what exactly caused those breaking changes in the past.
What this document outlines (in my understanding) is that any experimental feature development can _only_ be visible behind --std=experimental, and the dependency of ghc-experimental. Unless those are given, the compiler should accept existing programs. This should allow us enough room to innovate (everyone is always free to opt-in to bleeding edge features with --std=experimental). I also believe that most of what we have today will need to be treated as non-experimental simply because we did not have that mechanism before. We don't want to break existing programs as much as possible, thus relegating existing features into --std=experimental (except for some fairly clear ones: e.g. Dependent Haskell, and Linear Types?) is not really possible. What we can however do is start deprecation phases for a few versions, moving features we consider highly experimental (or maybe even bad) into `--std=experimental`. Just by having deprecation phases and given the ecosystem enough time to adjust (and provide feedback) we might come to different conclusions.
As I've also outlined in the document, _if_ GHC was trivially swappable, companies like IOG would _love_ to try new compilers and report back bugs and regressions. As it is today, we can't. Making a large live codebase compatible with 9.8 is a multiple weeks effort. Experimenting with nightlies is technically impossible. _If_ I could setup the built of our software trivial with ghc nightlies, I'd be _happy_ to build the infrastructure out it to provide performance regressions (compilation, runtime, ...) for our codebase and provide the feedback to the GHC team; however I can't. And thus I'm stuck patching and fixing 8.10, and 9.2 today. 9.6 maybe soon, but likely at the point in time where 9.6 is not going to see any further releases, so I can spare trying to even forward port my patches to HEAD. Not that I could even test them with head properly, as our source is not accepted by HEAD. Thus I end up writing patches against old stale branches. This to me is a fairly big discouragement from contributing to GHC.
Best, Moritz
On Mon, 25 Sept 2023 at 15:17, Adam Gundry <adam@well-typed.com> wrote:
I'm afraid that I'm somewhat sceptical of this approach.
A strong stability guarantee is certainly a valuable goal, but it also comes with costs, which I'd like to see more clearly articulated. Some of them include:
* Cognitive overhead for users, because of the inability to remove complexity from the design.
* Increasing maintenance burden in the compiler, because of the additional work needed to implement new features and the inability to remove complexity from the implementation.
* A risk of getting stuck in a local optimum, because moving to a better design would entail breaking changes.
* Discouraging volunteer contributors, who are much less likely to work on a potentially beneficial change if the process for getting it approved is too onerous. (I'm worried we're already reaching that point due to the increasing burden of well-intentioned processes.)
Ultimately every proposed change has a cost-benefit trade-off, with risk of breakage being one of the costs. We need to consciously evaluate that trade-off on a case-by-case basis. Almost all changes might break something (e.g. by regressing performance, or for Hyrum's Law reasons), so there needs to be a proportionate assessment of how likely each change is to be damaging in practice, bearing in mind that such an assessment is itself costly and limited in scope.
It seems to me that the GHC team have taken on board lessons regarding stability of the language, and the extension system already gives quite a lot of flexibility to evolve the language in a backwards-compatible way. In my experience, the key stability problems preventing upgrades to recent GHC releases are:
* The cascading effect of breaking changes in one library causing the need to upgrade libraries which depend upon it. This is primarily under the control of the CLC and library maintainers, however, not the GHC team. It would help if base was minimal and reinstallable, but that isn't a total solution either, because you'd still have to worry about packages depending on template-haskell or the ghc package itself.
* Performance regressions or critical bugs. These tend to be a significant obstacle to upgrading for smaller commercial users. But spending more of our limited resources on stability of the language means fewer resources for resolving these issues.
There's surely more we can do here, but let's be careful not to pay too many costs to achieve stability of the *language* alone, when stability of the *libraries* and *implementation* are both more important and harder to fix.
Adam
On 22/09/2023 10:53, Simon Peyton Jones wrote:
Dear GHC SC
To avoid derailing the debate about -Wsevere < https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, and HasField redesign < https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, I'm starting a new (email for now) thread about stability.
I have tried to articulate what I believe is an evolving consensus in this document < https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47Zulga... .
If we converge, we'll turn that into a proper PR for the GHC proposal process, although it has wider implications than just GHC proposals and we should share with a broader audience. But let's start with the steering committee.
Any views? You all have edit rights.
I think that the draft covers Moritz's and Julian's goals, at least that was my intention. I have pasted Moritz's last email below, for context.
Simon
========= Moritz's last email ============
Now, this is derailing the original discussion a bit, and I'm not sure how far we want to take this. But, regarding @Simon Marlow <mailto:marlowsd@gmail.com>'s comment
This is one cultural aspect of our community I'd like to shift: the expectation that it's OK to make breaking changes as long as you warn about them or go through a migration cycle. It just isn't! (and I speak as someone who used to make lots of changes, I'm now fully repentant!). That's not to say that we shouldn't ever change anything, but when considering the cost/benefit tradeoff adding a migration cycle doesn't reduce the cost, it just defers it.
I actually read this as we should stop having breaking changes to begin with. And _if_ we do have breaking changes, that deprecation does not change the need to actually change code (cost). As outlined in my reply to that, and @Richard Eisenberg <mailto:lists@richarde.dev>'s observation, it "smears" the cost. The--to me--_much_ bigger implication of deprecation cycles is that we _inform_ our _customers_ about upcoming changes _early_, instead of _after the fact_. We also give them ample time to react. Being by changing their code, or raising their concerns. Would the Simplified Subsumptions / Deep Subsumptions change have looked differently? As such I see deprecation cycles as orthogonal to the question if we should have breaking changes to begin with.
Thus I believe the following:
- Do have a deprecation cycle if possible. - Do not treat a deprecation cycle as an excuse. Costs are deferred but are as large as ever.
should be upgraded to: - Preferably _no_ breaking changes. - If breaking changes, then with a deprecation cycle, unless technically infeasible. - An understanding that any breaking change incurs significant costs.
Ocaml recently added multicore support, and they put tremendous effort into making sure it keeps backwards compatibility: https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md <https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md
PS: we should also agree that a "stable" extension should not require dependencies on ghc-experimental. To become stable, any library support for an extension must move into `base`.
This seems like a good idea, however I still remain that _experimental_ features should not be on-by-default in a stable compiler. Yes, ideally I'd not even see them in a stable compiler, but I know this view is contentious. The use of `ghc-experimental` should therefore be guarded by `--std=experimental` as Julian suggested. That is a loud opt-in to experimental features.
-- Adam Gundry, Haskell Consultant Well-Typed LLP, https://www.well-typed.com/
Registered in England & Wales, OC335890 27 Old Gloucester Street, London WC1N 3AX, England <https://www.google.com/maps/search/27+Old+Gloucester+Street,+London+WC1N+3AX,+England?entry=gmail&source=g>
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org
https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
I do not yet see how we can end up with the inability to change. We will just have a clearer process for _breaking_ changes. This
does absolutely not mean we have to end up in a local optimum, or that we
can not change. We can
Agreed that stable features are not unable to change... it's just that the bar is higher (that's the intent), so change is more expensive. E.g. suppose we want to change some fine point about the semantics of INCOHERENT. It might be difficult to have both the old semantics and the new, and somehow give a deprecation warning. And INCOHERENT is already saying "I know that the ice is thin here and I'm signed up to the consequences". You are reminding us that if a feature is widely depended on, changing it imposes real costs on users. I'm reminding us that making more things "stable" imposes real costs on GHC's design and implementation team -- on whom we all rely. Both concerns are legitimate. We will need to debate each stable/experimental choice on a case by case basis, informed (among other things) but how widely used they are. Simon On Thu, 28 Sept 2023 at 13:39, Moritz Angermann <moritz.angermann@gmail.com> wrote:
Simon,
Thank you for bringing us this far. I'd be happy to step up to drive this further.
I will say that I do see the tension you see as well. And I do believe if we come to a conclusion on this stability policy that it will make GHC development more rigorous, which I think is a good thing for all of us, not just the consumers of the compiler. I think we need to stay mindful that we can still freely experiment on the --std=experimental (or however that flag ends up being named) side. I see this whole discussion as leading us towards the language research reactor side of GHC being primarily confined behind --std=experimental, and the stability seeking (commercial application?) on the other side.
I do not yet see how we can end up with the inability to change. We will just have a clearer process for _breaking_ changes. This does absolutely not mean we have to end up in a local optimum, or that we can not change. We can!
Unless someone speaks up who does _not_ want me to drive, this, I'm happy to start driving this discussion (including writing the proposals, starting next week).
Best, Moritz
On Thu, 28 Sept 2023 at 19:30, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Should we have a document (or better spreadsheet?) with a bullet point
for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
I think that would be a helpful way to "ground" the discussion a bit more. (The spreadsheet should also give a preliminary classification of extensions, at least into stable/experimental.)
I'm running out of capacity to drive this debate, useful though it is. Does anyone else feel able to drive some of the legwork?
So far this is all informal committee discussion. The next step would be a GHC Proposal inviting broader feedback from the community. I'm just hoping that by debugging it between ourselves we can side-step some unproductive discussions in that bigger context.
I believe we need to take into account that we can’t end up classifying
most of todays Haskell programs unstable
There is a tension here. If we say something is "stable" then we have to be super-careful about changing it. (That's the whole point.) And yet if the feature (like INCOHERENT) is a flaky "you are on your own" unsafePerformIO-like feature, I am axious about tying ourselves into an inability to change the behaviour of corner cases. I'm not sure how to resolve this tension.
Simon
On Thu, 28 Sept 2023 at 02:20, Moritz Angermann < moritz.angermann@gmail.com> wrote:
I think we are moving in the right direction! I do see however the tension rising on (2). And without being clear about (2), I don’t think we can properly agree on (1). We can agree on (1) in principle, but we need to clarify what we consider unstable/experimental, as a precondition to have finale agreement on (1). Otherwise people might agree to (1), only to be surprised by (2). For (3), I’d be happy to try to get my employer to provide resources for the implementation of —std=experimental.
Thusly I believe we should start to build a list of features we consider sufficiently experimental that they should preclude an existing Haskell program from being considered stable. This list for me contains so far:
- Linear Types - Dependent Haskell
Adam pointed out experimental backend and non-tire-1 platforms. I tend to agree with this, but see this distinctly separate from the language stability (outside of backend specific language extensions, e.g. JSFFI).
Platforms/backends may be experimental but those are (safe for specific lang exts) orthogonal to the Haskell code the compiler accepts.
Should we have a document (or better spreadsheet?) with a bullet point for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
Best, Moritz
On Wed, 27 Sep 2023 at 10:35 PM, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
it's essential that we continue to have these discussions to ensure
we're making the best decisions for the project and our community.
Yes exactly! Its tricky and nuanced; hence trying to articulate something in a concrete doc, so we are all on the same page (literally!).
However, deprecation cycles don't mean we're averse to major changes.
It means we introduce them responsibly. When we believe a superior design is possible, we can start a deprecation process to transition towards it.
I have tried to make this explicit in Section 4. See what you think.
I think there are three phases
1. Agree this document. Is it what we want. 2. Categorise extensions into stable/experimental, and identify experimental language features. 3. Implement --std=experimental (Section 6).
(1) is what we are doing now. (2) will be some work, done by us. (3) is a larger task: it will require significant work to implement, and may impose unwelcome churn of its own. But that should not stop us doing (1) and (2).
Simon
-
On Wed, 27 Sept 2023 at 10:20, Moritz Angermann < moritz.angermann@gmail.com> wrote:
Dear Adam,
Thank you for your thoughtful feedback. I understand your reservations, and it's essential that we continue to have these discussions to ensure we're making the best decisions for the project and our community. Let me address each of your points in turn: - Cognitive Overhead for Users: I understand the concern about cognitive overhead due to the inability to remove complexity. However, our primary intention is to ensure a gradual transition for our users rather than abrupt shifts. Introducing changes via deprecation cycles allows users to adjust to modifications over time, reducing the immediate cognitive load. It's a balance between stability and simplicity, and I believe this approach allows us still to reduce complexity.
- Maintenance Burden in the Compiler: Maintaining backward compatibility does indeed introduce some overhead. Still, it also encourages a more disciplined and considered approach to changes. With our deprecation cycles in place, it's not that we never remove complexity; rather, we do it in a way that provides ample time for adjustments. This benefits both the development team and the community.
- Risk of Local Optimum: This is a valid concern. However, deprecation cycles don't mean we're averse to major changes. It means we introduce them responsibly. When we believe a superior design is possible, we can start a deprecation process to transition towards it. The flexibility and duration of our deprecation cycles can be tailored depending on the severity of the breaking change.
- Discouraging Volunteer Contributors: I understand that lengthy approval processes can be off-putting. But it's crucial to note that a rigorous process ensures the consistency and reliability of our project. We always welcome and value contributions. Moreover, I believe this stability policy will provide us with clear guardrails on how changes can be contributed.
I will not disagree on the costs. I do believe though that the costs for _breaking_ changes in the compiler ought to be borne by the people making the change, instead of those who use the compiler (and may not even benefit of those changes that caused breakage). I also see the team maintaining GHC as the one to enforce this; they are the ones who cut the releases. The fact that we may have breaking changes due to _bugs_ is covered explicitly in the stability policy document.
With my CLC hat on, I have been focusing on the same stability guidelines as well (if it breaks existing code, I have been against those changes without deprecation policies). The issues with the template-haskell, and ghc library are noted. For the ghc library the question will remain if we intent to provide a stable api to the compiler or not. I believe many tools would like to have one, and if we relegate anything unstable to ghc-experimental this might be achieved. For template-haskell this is a bigger concern. Maybe we can collectively come up with a solution that would allow us to provide a more insulated template haskell interface from the compiler.
However for template-haskell we might also need to look at what exactly caused those breaking changes in the past.
What this document outlines (in my understanding) is that any experimental feature development can _only_ be visible behind --std=experimental, and the dependency of ghc-experimental. Unless those are given, the compiler should accept existing programs. This should allow us enough room to innovate (everyone is always free to opt-in to bleeding edge features with --std=experimental). I also believe that most of what we have today will need to be treated as non-experimental simply because we did not have that mechanism before. We don't want to break existing programs as much as possible, thus relegating existing features into --std=experimental (except for some fairly clear ones: e.g. Dependent Haskell, and Linear Types?) is not really possible. What we can however do is start deprecation phases for a few versions, moving features we consider highly experimental (or maybe even bad) into `--std=experimental`. Just by having deprecation phases and given the ecosystem enough time to adjust (and provide feedback) we might come to different conclusions.
As I've also outlined in the document, _if_ GHC was trivially swappable, companies like IOG would _love_ to try new compilers and report back bugs and regressions. As it is today, we can't. Making a large live codebase compatible with 9.8 is a multiple weeks effort. Experimenting with nightlies is technically impossible. _If_ I could setup the built of our software trivial with ghc nightlies, I'd be _happy_ to build the infrastructure out it to provide performance regressions (compilation, runtime, ...) for our codebase and provide the feedback to the GHC team; however I can't. And thus I'm stuck patching and fixing 8.10, and 9.2 today. 9.6 maybe soon, but likely at the point in time where 9.6 is not going to see any further releases, so I can spare trying to even forward port my patches to HEAD. Not that I could even test them with head properly, as our source is not accepted by HEAD. Thus I end up writing patches against old stale branches. This to me is a fairly big discouragement from contributing to GHC.
Best, Moritz
On Mon, 25 Sept 2023 at 15:17, Adam Gundry <adam@well-typed.com> wrote:
I'm afraid that I'm somewhat sceptical of this approach.
A strong stability guarantee is certainly a valuable goal, but it also comes with costs, which I'd like to see more clearly articulated. Some of them include:
* Cognitive overhead for users, because of the inability to remove complexity from the design.
* Increasing maintenance burden in the compiler, because of the additional work needed to implement new features and the inability to remove complexity from the implementation.
* A risk of getting stuck in a local optimum, because moving to a better design would entail breaking changes.
* Discouraging volunteer contributors, who are much less likely to work on a potentially beneficial change if the process for getting it approved is too onerous. (I'm worried we're already reaching that point due to the increasing burden of well-intentioned processes.)
Ultimately every proposed change has a cost-benefit trade-off, with risk of breakage being one of the costs. We need to consciously evaluate that trade-off on a case-by-case basis. Almost all changes might break something (e.g. by regressing performance, or for Hyrum's Law reasons), so there needs to be a proportionate assessment of how likely each change is to be damaging in practice, bearing in mind that such an assessment is itself costly and limited in scope.
It seems to me that the GHC team have taken on board lessons regarding stability of the language, and the extension system already gives quite a lot of flexibility to evolve the language in a backwards-compatible way. In my experience, the key stability problems preventing upgrades to recent GHC releases are:
* The cascading effect of breaking changes in one library causing the need to upgrade libraries which depend upon it. This is primarily under the control of the CLC and library maintainers, however, not the GHC team. It would help if base was minimal and reinstallable, but that isn't a total solution either, because you'd still have to worry about packages depending on template-haskell or the ghc package itself.
* Performance regressions or critical bugs. These tend to be a significant obstacle to upgrading for smaller commercial users. But spending more of our limited resources on stability of the language means fewer resources for resolving these issues.
There's surely more we can do here, but let's be careful not to pay too many costs to achieve stability of the *language* alone, when stability of the *libraries* and *implementation* are both more important and harder to fix.
Adam
On 22/09/2023 10:53, Simon Peyton Jones wrote: > Dear GHC SC > > To avoid derailing the debate about -Wsevere > < https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, and HasField redesign < https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, I'm starting a new (email for now) thread about stability. > > I have tried to articulate what I believe is an evolving consensus in > this document > < https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47Zulga... >. > > If we converge, we'll turn that into a proper PR for the GHC proposal > process, although it has wider implications than just GHC proposals and > we should share with a broader audience. But let's start with the > steering committee. > > Any views? You all have edit rights. > > I think that the draft covers Moritz's and Julian's goals, at least that > was my intention. I have pasted Moritz's last email below, for context. > > Simon > > > ========= Moritz's last email ============ > > Now, this is derailing the original discussion a bit, and I'm not sure > how far we want to take this. But, regarding @Simon Marlow > <mailto:marlowsd@gmail.com>'s comment > > This is one cultural aspect of our community I'd like to shift: the > expectation that it's OK to make breaking changes as long as you > warn about > them or go through a migration cycle. It just isn't! (and I speak as > someone who used to make lots of changes, I'm now fully repentant!). > That's > not to say that we shouldn't ever change anything, but when > considering the > cost/benefit tradeoff adding a migration cycle doesn't reduce the > cost, it > just defers it. > > > I actually read this as we should stop having breaking changes to begin > with. And _if_ we > do have breaking changes, that deprecation does not change the need to > actually change > code (cost). As outlined in my reply to that, and @Richard Eisenberg > <mailto:lists@richarde.dev>'s observation, it > "smears" the cost. The--to me--_much_ bigger implication of deprecation > cycles is that we > _inform_ our _customers_ about upcoming changes _early_, instead of > _after the fact_. We > also give them ample time to react. Being by changing their code, or > raising their concerns. > Would the Simplified Subsumptions / Deep Subsumptions change have looked > differently? > As such I see deprecation cycles as orthogonal to the question if we > should have breaking > changes to begin with. > > Thus I believe the following: > > - Do have a deprecation cycle if possible. > - Do not treat a deprecation cycle as an excuse. Costs are deferred > but are as large as ever. > > > should be upgraded to: > - Preferably _no_ breaking changes. > - If breaking changes, then with a deprecation cycle, unless technically > infeasible. > - An understanding that any breaking change incurs significant costs. > > Ocaml recently added multicore support, and they put tremendous effort > into making > sure it keeps backwards compatibility: > https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md > < https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md> > > PS: we should also agree that a "stable" extension should not > require dependencies on ghc-experimental. To become stable, any > library support for an extension must move into `base`. > > > This seems like a good idea, however I still remain that _experimental_ > features should not be on-by-default in a stable compiler. Yes, ideally > I'd not even see them in a stable compiler, but I know this view is > contentious. The use of `ghc-experimental` should therefore be guarded > by `--std=experimental` as Julian suggested. That is a loud opt-in to > experimental features. >
-- Adam Gundry, Haskell Consultant Well-Typed LLP, https://www.well-typed.com/
Registered in England & Wales, OC335890 27 Old Gloucester Street, London WC1N 3AX, England <https://www.google.com/maps/search/27+Old+Gloucester+Street,+London+WC1N+3AX,+England?entry=gmail&source=g>
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org
https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org
https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
I haven't quite been keeping up with all of this thread, but I'm glad to see we are making progress and exploring the trade-offs here. Moritz, thanks for volunteering to drive this forward and start writing a proposal. I'm very happy for you to do so; while we may need to continue seeking the right balance between the different concerns, it's a good discussion to be having. I agree with the suggestion to keep the plan for --std=experimental (which is about an enforcement mechanism) separate from the policy aspects (i.e. what stability guarantees do we offer for which features). I can see that having some sort of flag may be helpful, but I'm not yet convinced we can reasonably give a simple binary "stable or not" classification, and that will become clearer once we more clearly categorise features and explore the library stability issue more. On the template-haskell front, I opened https://gitlab.haskell.org/ghc/ghc/-/issues/24021 which explores one possible way forward. Generalising from that ticket, it seems to me that the biggest step we could make towards greater stability would be to move away from non-reinstallable packages tied to the compiler (like base and template-haskell as they stand) towards reinstallable packages. For example, if base was a reinstallable package then it could receive a new minor version to support a new version of ghc-internal, without breaking its clients. The CLC-approved addition of foldl' to Prelude looks set to cause a lot of disruption, but if we could use an old major version of base with the new GHC, that would be ameliorated significantly. This seems like somewhere where more resources could really help. Finally, in case this is useful, I started talking to the authors of the extension stability proposal a little while back about classifying extensions, and prepared a very drafty spreadsheet with some initial thoughts. Take it with a pinch of salt, but here it is: https://docs.google.com/spreadsheets/d/1sRIcNKdflX2ogrx2EF3vKOn0vmv-UEOdladB... Cheers, Adam On 28/09/2023 14:15, Simon Peyton Jones wrote:
I do not yet see how we can end up with the inability to change. We will just have a clearer process for _breaking_ changes. This
does absolutely not mean we have to end up in a local optimum, or that we can not change. We can
Agreed that stable features are not unable to change... it's just that the bar is higher (that's the intent), so change is more expensive. E.g. suppose we want to change some fine point about the semantics of INCOHERENT. It might be difficult to have both the old semantics and the new, and somehow give a deprecation warning. And INCOHERENT is already saying "I know that the ice is thin here and I'm signed up to the consequences".
You are reminding us that if a feature is widely depended on, changing it imposes real costs on users. I'm reminding us that making more things "stable" imposes real costs on GHC's design and implementation team -- on whom we all rely. Both concerns are legitimate. We will need to debate each stable/experimental choice on a case by case basis, informed (among other things) but how widely used they are.
Simon
On Thu, 28 Sept 2023 at 13:39, Moritz Angermann <moritz.angermann@gmail.com <mailto:moritz.angermann@gmail.com>> wrote:
Simon,
Thank you for bringing us this far. I'd be happy to step up to drive this further.
I will say that I do see the tension you see as well. And I do believe if we come to a conclusion on this stability policy that it will make GHC development more rigorous, which I think is a good thing for all of us, not just the consumers of the compiler. I think we need to stay mindful that we can still freely experiment on the --std=experimental (or however that flag ends up being named) side. I see this whole discussion as leading us towards the language research reactor side of GHC being primarily confined behind --std=experimental, and the stability seeking (commercial application?) on the other side.
I do not yet see how we can end up with the inability to change. We will just have a clearer process for _breaking_ changes. This does absolutely not mean we have to end up in a local optimum, or that we can not change. We can!
Unless someone speaks up who does _not_ want me to drive, this, I'm happy to start driving this discussion (including writing the proposals, starting next week).
Best, Moritz
On Thu, 28 Sept 2023 at 19:30, Simon Peyton Jones <simon.peytonjones@gmail.com <mailto:simon.peytonjones@gmail.com>> wrote:
Should we have a document (or better spreadsheet?) with a bullet point for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
I think that would be a helpful way to "ground" the discussion a bit more. (The spreadsheet should also give a preliminary classification of extensions, at least into stable/experimental.)
I'm running out of capacity to drive this debate, useful though it is. Does anyone else feel able to drive some of the legwork?
So far this is all informal committee discussion. The next step would be a GHC Proposal inviting broader feedback from the community. I'm just hoping that by debugging it between ourselves we can side-step some unproductive discussions in that bigger context.
I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable
There is a tension here. If we say something is "stable" then we have to be super-careful about changing it. (That's the whole point.) And yet if the feature (like INCOHERENT) is a flaky "you are on your own" unsafePerformIO-like feature, I am axious about tying ourselves into an inability to change the behaviour of corner cases. I'm not sure how to resolve this tension.
Simon
On Thu, 28 Sept 2023 at 02:20, Moritz Angermann <moritz.angermann@gmail.com <mailto:moritz.angermann@gmail.com>> wrote:
I think we are moving in the right direction! I do see however the tension rising on (2). And without being clear about (2), I don’t think we can properly agree on (1). We can agree on (1) in principle, but we need to clarify what we consider unstable/experimental, as a precondition to have finale agreement on (1). Otherwise people might agree to (1), only to be surprised by (2). For (3), I’d be happy to try to get my employer to provide resources for the implementation of —std=experimental.
Thusly I believe we should start to build a list of features we consider sufficiently experimental that they should preclude an existing Haskell program from being considered stable. This list for me contains so far:
- Linear Types - Dependent Haskell
Adam pointed out experimental backend and non-tire-1 platforms. I tend to agree with this, but see this distinctly separate from the language stability (outside of backend specific language extensions, e.g. JSFFI).
Platforms/backends may be experimental but those are (safe for specific lang exts) orthogonal to the Haskell code the compiler accepts.
Should we have a document (or better spreadsheet?) with a bullet point for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
Best, Moritz
On Wed, 27 Sep 2023 at 10:35 PM, Simon Peyton Jones <simon.peytonjones@gmail.com <mailto:simon.peytonjones@gmail.com>> wrote:
it's essential that we continue to have these discussions to ensure we're making the best decisions for the project and our community.
Yes exactly! Its tricky and nuanced; hence trying to articulate something in a concrete doc, so we are all on the same page (literally!).
However, deprecation cycles don't mean we're averse to major changes. It means we introduce them responsibly. When we believe a superior design is possible, we can start a deprecation process to transition towards it.
I have tried to make this explicit in Section 4. See what you think.
I think there are three phases
1. Agree this document. Is it what we want. 2. Categorise extensions into stable/experimental, and identify experimental language features. 3. Implement --std=experimental (Section 6).
(1) is what we are doing now. (2) will be some work, done by us. (3) is a larger task: it will require significant work to implement, and may impose unwelcome churn of its own. But that should not stop us doing (1) and (2).
Simon
*
On Wed, 27 Sept 2023 at 10:20, Moritz Angermann <moritz.angermann@gmail.com <mailto:moritz.angermann@gmail.com>> wrote:
Dear Adam,
Thank you for your thoughtful feedback. I understand your reservations, and it's essential that we continue to have these discussions to ensure we're making the best decisions for the project and our community. Let me address each of your points in turn:
- Cognitive Overhead for Users: I understand the concern about cognitive overhead due to the inability to remove complexity. However, our primary intention is to ensure a gradual transition for our users rather than abrupt shifts. Introducing changes via deprecation cycles allows users to adjust to modifications over time, reducing the immediate cognitive load. It's a balance between stability and simplicity, and I believe this approach allows us still to reduce complexity.
- Maintenance Burden in the Compiler: Maintaining backward compatibility does indeed introduce some overhead. Still, it also encourages a more disciplined and considered approach to changes. With our deprecation cycles in place, it's not that we never remove complexity; rather, we do it in a way that provides ample time for adjustments. This benefits both the development team and the community.
- Risk of Local Optimum: This is a valid concern. However, deprecation cycles don't mean we're averse to major changes. It means we introduce them responsibly. When we believe a superior design is possible, we can start a deprecation process to transition towards it. The flexibility and duration of our deprecation cycles can be tailored depending on the severity of the breaking change.
- Discouraging Volunteer Contributors: I understand that lengthy approval processes can be off-putting. But it's crucial to note that a rigorous process ensures the consistency and reliability of our project. We always welcome and value contributions. Moreover, I believe this stability policy will provide us with clear guardrails on how changes can be contributed.
I will not disagree on the costs. I do believe though that the costs for _breaking_ changes in the compiler ought to be borne by the people making the change, instead of those who use the compiler (and may not even benefit of those changes that caused breakage). I also see the team maintaining GHC as the one to enforce this; they are the ones who cut the releases. The fact that we may have breaking changes due to _bugs_ is covered explicitly in the stability policy document.
With my CLC hat on, I have been focusing on the same stability guidelines as well (if it breaks existing code, I have been against those changes without deprecation policies). The issues with the template-haskell, and ghc library are noted. For the ghc library the question will remain if we intent to provide a stable api to the compiler or not. I believe many tools would like to have one, and if we relegate anything unstable to ghc-experimental this might be achieved. For template-haskell this is a bigger concern. Maybe we can collectively come up with a solution that would allow us to provide a more insulated template haskell interface from the compiler.
However for template-haskell we might also need to look at what exactly caused those breaking changes in the past.
What this document outlines (in my understanding) is that any experimental feature development can _only_ be visible behind --std=experimental, and the dependency of ghc-experimental. Unless those are given, the compiler should accept existing programs. This should allow us enough room to innovate (everyone is always free to opt-in to bleeding edge features with --std=experimental). I also believe that most of what we have today will need to be treated as non-experimental simply because we did not have that mechanism before. We don't want to break existing programs as much as possible, thus relegating existing features into --std=experimental (except for some fairly clear ones: e.g. Dependent Haskell, and Linear Types?) is not really possible. What we can however do is start deprecation phases for a few versions, moving features we consider highly experimental (or maybe even bad) into `--std=experimental`. Just by having deprecation phases and given the ecosystem enough time to adjust (and provide feedback) we might come to different conclusions.
As I've also outlined in the document, _if_ GHC was trivially swappable, companies like IOG would _love_ to try new compilers and report back bugs and regressions. As it is today, we can't. Making a large live codebase compatible with 9.8 is a multiple weeks effort. Experimenting with nightlies is technically impossible. _If_ I could setup the built of our software trivial with ghc nightlies, I'd be _happy_ to build the infrastructure out it to provide performance regressions (compilation, runtime, ...) for our codebase and provide the feedback to the GHC team; however I can't. And thus I'm stuck patching and fixing 8.10, and 9.2 today. 9.6 maybe soon, but likely at the point in time where 9.6 is not going to see any further releases, so I can spare trying to even forward port my patches to HEAD. Not that I could even test them with head properly, as our source is not accepted by HEAD. Thus I end up writing patches against old stale branches. This to me is a fairly big discouragement from contributing to GHC.
Best, Moritz
On Mon, 25 Sept 2023 at 15:17, Adam Gundry <adam@well-typed.com <mailto:adam@well-typed.com>> wrote:
I'm afraid that I'm somewhat sceptical of this approach.
A strong stability guarantee is certainly a valuable goal, but it also comes with costs, which I'd like to see more clearly articulated. Some of them include:
* Cognitive overhead for users, because of the inability to remove complexity from the design.
* Increasing maintenance burden in the compiler, because of the additional work needed to implement new features and the inability to remove complexity from the implementation.
* A risk of getting stuck in a local optimum, because moving to a better design would entail breaking changes.
* Discouraging volunteer contributors, who are much less likely to work on a potentially beneficial change if the process for getting it approved is too onerous. (I'm worried we're already reaching that point due to the increasing burden of well-intentioned processes.)
Ultimately every proposed change has a cost-benefit trade-off, with risk of breakage being one of the costs. We need to consciously evaluate that trade-off on a case-by-case basis. Almost all changes might break something (e.g. by regressing performance, or for Hyrum's Law reasons), so there needs to be a proportionate assessment of how likely each change is to be damaging in practice, bearing in mind that such an assessment is itself costly and limited in scope.
It seems to me that the GHC team have taken on board lessons regarding stability of the language, and the extension system already gives quite a lot of flexibility to evolve the language in a backwards-compatible way. In my experience, the key stability problems preventing upgrades to recent GHC releases are:
* The cascading effect of breaking changes in one library causing the need to upgrade libraries which depend upon it. This is primarily under the control of the CLC and library maintainers, however, not the GHC team. It would help if base was minimal and reinstallable, but that isn't a total solution either, because you'd still have to worry about packages depending on template-haskell or the ghc package itself.
* Performance regressions or critical bugs. These tend to be a significant obstacle to upgrading for smaller commercial users. But spending more of our limited resources on stability of the language means fewer resources for resolving these issues.
There's surely more we can do here, but let's be careful not to pay too many costs to achieve stability of the *language* alone, when stability of the *libraries* and *implementation* are both more important and harder to fix.
Adam
On 22/09/2023 10:53, Simon Peyton Jones wrote: > Dear GHC SC > > To avoid derailing the debate about -Wsevere > <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003... <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>>, and HasField redesign <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003... <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>>, I'm starting a new (email for now) thread about stability. > > I have tried to articulate what I believe is an evolving consensus in > this document > <https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47Zulga... <https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47ZulgaZds/edit?usp=sharing>>. > > If we converge, we'll turn that into a proper PR for the GHC proposal > process, although it has wider implications than just GHC proposals and > we should share with a broader audience. But let's start with the > steering committee. > > Any views? You all have edit rights. > > I think that the draft covers Moritz's and Julian's goals, at least that > was my intention. I have pasted Moritz's last email below, for context. > > Simon > > > ========= Moritz's last email ============ > > Now, this is derailing the original discussion a bit, and I'm not sure > how far we want to take this. But, regarding @Simon Marlow > <mailto:marlowsd@gmail.com <mailto:marlowsd@gmail.com>>'s comment > > This is one cultural aspect of our community I'd like to shift: the > expectation that it's OK to make breaking changes as long as you > warn about > them or go through a migration cycle. It just isn't! (and I speak as > someone who used to make lots of changes, I'm now fully repentant!). > That's > not to say that we shouldn't ever change anything, but when > considering the > cost/benefit tradeoff adding a migration cycle doesn't reduce the > cost, it > just defers it. > > > I actually read this as we should stop having breaking changes to begin > with. And _if_ we > do have breaking changes, that deprecation does not change the need to > actually change > code (cost). As outlined in my reply to that, and @Richard Eisenberg > <mailto:lists@richarde.dev <mailto:lists@richarde.dev>>'s observation, it > "smears" the cost. The--to me--_much_ bigger implication of deprecation > cycles is that we > _inform_ our _customers_ about upcoming changes _early_, instead of > _after the fact_. We > also give them ample time to react. Being by changing their code, or > raising their concerns. > Would the Simplified Subsumptions / Deep Subsumptions change have looked > differently? > As such I see deprecation cycles as orthogonal to the question if we > should have breaking > changes to begin with. > > Thus I believe the following: > > - Do have a deprecation cycle if possible. > - Do not treat a deprecation cycle as an excuse. Costs are deferred > but are as large as ever. > > > should be upgraded to: > - Preferably _no_ breaking changes. > - If breaking changes, then with a deprecation cycle, unless technically > infeasible. > - An understanding that any breaking change incurs significant costs. > > Ocaml recently added multicore support, and they put tremendous effort > into making > sure it keeps backwards compatibility: > https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md <https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md> > <https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md <https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md>> > > PS: we should also agree that a "stable" extension should not > require dependencies on ghc-experimental. To become stable, any > library support for an extension must move into `base`. > > > This seems like a good idea, however I still remain that _experimental_ > features should not be on-by-default in a stable compiler. Yes, ideally > I'd not even see them in a stable compiler, but I know this view is > contentious. The use of `ghc-experimental` should therefore be guarded > by `--std=experimental` as Julian suggested. That is a loud opt-in to > experimental features. >
-- Adam Gundry, Haskell Consultant Well-Typed LLP, https://www.well-typed.com/ Registered in England & Wales, OC335890 27 Old Gloucester Street, London WC1N 3AX, England
I have been pretty desperate for us to start taking stability seriously for some years now. Part of the reason for this is to give us the space to make breaking changes when we really need to. Should we discover a compelling reason to introduce a breaking change to the compiler then it would be difficult to do without creating a lot of resentment in the community because we have so little clarity in this area. If we succeed in establishing this framework then I would hope that we would find it easier to hold a conversation with the community about the kind of change that Adam is concerned about -- because we would have established credibility in this area. Chris
On 28 Sep 2023, at 14:15, Simon Peyton Jones <simon.peytonjones@gmail.com> wrote:
I do not yet see how we can end up with the inability to change. We will just have a clearer process for _breaking_ changes. This does absolutely not mean we have to end up in a local optimum, or that we can not change. We can
Agreed that stable features are not unable to change... it's just that the bar is higher (that's the intent), so change is more expensive. E.g. suppose we want to change some fine point about the semantics of INCOHERENT. It might be difficult to have both the old semantics and the new, and somehow give a deprecation warning. And INCOHERENT is already saying "I know that the ice is thin here and I'm signed up to the consequences".
You are reminding us that if a feature is widely depended on, changing it imposes real costs on users. I'm reminding us that making more things "stable" imposes real costs on GHC's design and implementation team -- on whom we all rely. Both concerns are legitimate. We will need to debate each stable/experimental choice on a case by case basis, informed (among other things) but how widely used they are.
Simon
On Thu, 28 Sept 2023 at 13:39, Moritz Angermann <moritz.angermann@gmail.com <mailto:moritz.angermann@gmail.com>> wrote:
Simon,
Thank you for bringing us this far. I'd be happy to step up to drive this further.
I will say that I do see the tension you see as well. And I do believe if we come to a conclusion on this stability policy that it will make GHC development more rigorous, which I think is a good thing for all of us, not just the consumers of the compiler. I think we need to stay mindful that we can still freely experiment on the --std=experimental (or however that flag ends up being named) side. I see this whole discussion as leading us towards the language research reactor side of GHC being primarily confined behind --std=experimental, and the stability seeking (commercial application?) on the other side.
I do not yet see how we can end up with the inability to change. We will just have a clearer process for _breaking_ changes. This does absolutely not mean we have to end up in a local optimum, or that we can not change. We can!
Unless someone speaks up who does _not_ want me to drive, this, I'm happy to start driving this discussion (including writing the proposals, starting next week).
Best, Moritz
On Thu, 28 Sept 2023 at 19:30, Simon Peyton Jones <simon.peytonjones@gmail.com <mailto:simon.peytonjones@gmail.com>> wrote:
Should we have a document (or better spreadsheet?) with a bullet point for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
I think that would be a helpful way to "ground" the discussion a bit more. (The spreadsheet should also give a preliminary classification of extensions, at least into stable/experimental.)
I'm running out of capacity to drive this debate, useful though it is. Does anyone else feel able to drive some of the legwork?
So far this is all informal committee discussion. The next step would be a GHC Proposal inviting broader feedback from the community. I'm just hoping that by debugging it between ourselves we can side-step some unproductive discussions in that bigger context.
I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable
There is a tension here. If we say something is "stable" then we have to be super-careful about changing it. (That's the whole point.) And yet if the feature (like INCOHERENT) is a flaky "you are on your own" unsafePerformIO-like feature, I am axious about tying ourselves into an inability to change the behaviour of corner cases. I'm not sure how to resolve this tension.
Simon
On Thu, 28 Sept 2023 at 02:20, Moritz Angermann <moritz.angermann@gmail.com <mailto:moritz.angermann@gmail.com>> wrote:
I think we are moving in the right direction! I do see however the tension rising on (2). And without being clear about (2), I don’t think we can properly agree on (1). We can agree on (1) in principle, but we need to clarify what we consider unstable/experimental, as a precondition to have finale agreement on (1). Otherwise people might agree to (1), only to be surprised by (2). For (3), I’d be happy to try to get my employer to provide resources for the implementation of —std=experimental.
Thusly I believe we should start to build a list of features we consider sufficiently experimental that they should preclude an existing Haskell program from being considered stable. This list for me contains so far:
- Linear Types - Dependent Haskell
Adam pointed out experimental backend and non-tire-1 platforms. I tend to agree with this, but see this distinctly separate from the language stability (outside of backend specific language extensions, e.g. JSFFI).
Platforms/backends may be experimental but those are (safe for specific lang exts) orthogonal to the Haskell code the compiler accepts.
Should we have a document (or better spreadsheet?) with a bullet point for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
Best, Moritz
On Wed, 27 Sep 2023 at 10:35 PM, Simon Peyton Jones <simon.peytonjones@gmail.com <mailto:simon.peytonjones@gmail.com>> wrote:
it's essential that we continue to have these discussions to ensure we're making the best decisions for the project and our community.
Yes exactly! Its tricky and nuanced; hence trying to articulate something in a concrete doc, so we are all on the same page (literally!).
However, deprecation cycles don't mean we're averse to major changes. It means we introduce them responsibly. When we believe a superior design is possible, we can start a deprecation process to transition towards it.
I have tried to make this explicit in Section 4. See what you think.
I think there are three phases Agree this document. Is it what we want. Categorise extensions into stable/experimental, and identify experimental language features. Implement --std=experimental (Section 6). (1) is what we are doing now. (2) will be some work, done by us. (3) is a larger task: it will require significant work to implement, and may impose unwelcome churn of its own. But that should not stop us doing (1) and (2).
Simon
On Wed, 27 Sept 2023 at 10:20, Moritz Angermann <moritz.angermann@gmail.com <mailto:moritz.angermann@gmail.com>> wrote:
Dear Adam,
Thank you for your thoughtful feedback. I understand your reservations, and it's essential that we continue to have these discussions to ensure we're making the best decisions for the project and our community. Let me address each of your points in turn:
- Cognitive Overhead for Users: I understand the concern about cognitive overhead due to the inability to remove complexity. However, our primary intention is to ensure a gradual transition for our users rather than abrupt shifts. Introducing changes via deprecation cycles allows users to adjust to modifications over time, reducing the immediate cognitive load. It's a balance between stability and simplicity, and I believe this approach allows us still to reduce complexity.
- Maintenance Burden in the Compiler: Maintaining backward compatibility does indeed introduce some overhead. Still, it also encourages a more disciplined and considered approach to changes. With our deprecation cycles in place, it's not that we never remove complexity; rather, we do it in a way that provides ample time for adjustments. This benefits both the development team and the community.
- Risk of Local Optimum: This is a valid concern. However, deprecation cycles don't mean we're averse to major changes. It means we introduce them responsibly. When we believe a superior design is possible, we can start a deprecation process to transition towards it. The flexibility and duration of our deprecation cycles can be tailored depending on the severity of the breaking change.
- Discouraging Volunteer Contributors: I understand that lengthy approval processes can be off-putting. But it's crucial to note that a rigorous process ensures the consistency and reliability of our project. We always welcome and value contributions. Moreover, I believe this stability policy will provide us with clear guardrails on how changes can be contributed.
I will not disagree on the costs. I do believe though that the costs for _breaking_ changes in the compiler ought to be borne by the people making the change, instead of those who use the compiler (and may not even benefit of those changes that caused breakage). I also see the team maintaining GHC as the one to enforce this; they are the ones who cut the releases. The fact that we may have breaking changes due to _bugs_ is covered explicitly in the stability policy document.
With my CLC hat on, I have been focusing on the same stability guidelines as well (if it breaks existing code, I have been against those changes without deprecation policies). The issues with the template-haskell, and ghc library are noted. For the ghc library the question will remain if we intent to provide a stable api to the compiler or not. I believe many tools would like to have one, and if we relegate anything unstable to ghc-experimental this might be achieved. For template-haskell this is a bigger concern. Maybe we can collectively come up with a solution that would allow us to provide a more insulated template haskell interface from the compiler.
However for template-haskell we might also need to look at what exactly caused those breaking changes in the past.
What this document outlines (in my understanding) is that any experimental feature development can _only_ be visible behind --std=experimental, and the dependency of ghc-experimental. Unless those are given, the compiler should accept existing programs. This should allow us enough room to innovate (everyone is always free to opt-in to bleeding edge features with --std=experimental). I also believe that most of what we have today will need to be treated as non-experimental simply because we did not have that mechanism before. We don't want to break existing programs as much as possible, thus relegating existing features into --std=experimental (except for some fairly clear ones: e.g. Dependent Haskell, and Linear Types?) is not really possible. What we can however do is start deprecation phases for a few versions, moving features we consider highly experimental (or maybe even bad) into `--std=experimental`. Just by having deprecation phases and given the ecosystem enough time to adjust (and provide feedback) we might come to different conclusions.
As I've also outlined in the document, _if_ GHC was trivially swappable, companies like IOG would _love_ to try new compilers and report back bugs and regressions. As it is today, we can't. Making a large live codebase compatible with 9.8 is a multiple weeks effort. Experimenting with nightlies is technically impossible. _If_ I could setup the built of our software trivial with ghc nightlies, I'd be _happy_ to build the infrastructure out it to provide performance regressions (compilation, runtime, ...) for our codebase and provide the feedback to the GHC team; however I can't. And thus I'm stuck patching and fixing 8.10, and 9.2 today. 9.6 maybe soon, but likely at the point in time where 9.6 is not going to see any further releases, so I can spare trying to even forward port my patches to HEAD. Not that I could even test them with head properly, as our source is not accepted by HEAD. Thus I end up writing patches against old stale branches. This to me is a fairly big discouragement from contributing to GHC.
Best, Moritz
On Mon, 25 Sept 2023 at 15:17, Adam Gundry <adam@well-typed.com <mailto:adam@well-typed.com>> wrote: > I'm afraid that I'm somewhat sceptical of this approach. > > A strong stability guarantee is certainly a valuable goal, but it also > comes with costs, which I'd like to see more clearly articulated. Some > of them include: > > * Cognitive overhead for users, because of the inability to remove > complexity from the design. > > * Increasing maintenance burden in the compiler, because of the > additional work needed to implement new features and the inability to > remove complexity from the implementation. > > * A risk of getting stuck in a local optimum, because moving to a > better design would entail breaking changes. > > * Discouraging volunteer contributors, who are much less likely to > work on a potentially beneficial change if the process for getting it > approved is too onerous. (I'm worried we're already reaching that point > due to the increasing burden of well-intentioned processes.) > > Ultimately every proposed change has a cost-benefit trade-off, with risk > of breakage being one of the costs. We need to consciously evaluate that > trade-off on a case-by-case basis. Almost all changes might break > something (e.g. by regressing performance, or for Hyrum's Law reasons), > so there needs to be a proportionate assessment of how likely each > change is to be damaging in practice, bearing in mind that such an > assessment is itself costly and limited in scope. > > It seems to me that the GHC team have taken on board lessons regarding > stability of the language, and the extension system already gives quite > a lot of flexibility to evolve the language in a backwards-compatible > way. In my experience, the key stability problems preventing upgrades to > recent GHC releases are: > > * The cascading effect of breaking changes in one library causing the > need to upgrade libraries which depend upon it. This is primarily under > the control of the CLC and library maintainers, however, not the GHC > team. It would help if base was minimal and reinstallable, but that > isn't a total solution either, because you'd still have to worry about > packages depending on template-haskell or the ghc package itself. > > * Performance regressions or critical bugs. These tend to be a > significant obstacle to upgrading for smaller commercial users. But > spending more of our limited resources on stability of the language > means fewer resources for resolving these issues. > > There's surely more we can do here, but let's be careful not to pay too > many costs to achieve stability of the *language* alone, when stability > of the *libraries* and *implementation* are both more important and > harder to fix. > > Adam > > > On 22/09/2023 10:53, Simon Peyton Jones wrote: > > Dear GHC SC > > > > To avoid derailing the debate about -Wsevere > > <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, and HasField redesign <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, I'm starting a new (email for now) thread about stability. > > > > I have tried to articulate what I believe is an evolving consensus in > > this document > > <https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47ZulgaZds/edit?usp=sharing>. > > > > If we converge, we'll turn that into a proper PR for the GHC proposal > > process, although it has wider implications than just GHC proposals and > > we should share with a broader audience. But let's start with the > > steering committee. > > > > Any views? You all have edit rights. > > > > I think that the draft covers Moritz's and Julian's goals, at least that > > was my intention. I have pasted Moritz's last email below, for context. > > > > Simon > > > > > > ========= Moritz's last email ============ > > > > Now, this is derailing the original discussion a bit, and I'm not sure > > how far we want to take this. But, regarding @Simon Marlow > > <mailto:marlowsd@gmail.com <mailto:marlowsd@gmail.com>>'s comment > > > > This is one cultural aspect of our community I'd like to shift: the > > expectation that it's OK to make breaking changes as long as you > > warn about > > them or go through a migration cycle. It just isn't! (and I speak as > > someone who used to make lots of changes, I'm now fully repentant!). > > That's > > not to say that we shouldn't ever change anything, but when > > considering the > > cost/benefit tradeoff adding a migration cycle doesn't reduce the > > cost, it > > just defers it. > > > > > > I actually read this as we should stop having breaking changes to begin > > with. And _if_ we > > do have breaking changes, that deprecation does not change the need to > > actually change > > code (cost). As outlined in my reply to that, and @Richard Eisenberg > > <mailto:lists@richarde.dev <mailto:lists@richarde.dev>>'s observation, it > > "smears" the cost. The--to me--_much_ bigger implication of deprecation > > cycles is that we > > _inform_ our _customers_ about upcoming changes _early_, instead of > > _after the fact_. We > > also give them ample time to react. Being by changing their code, or > > raising their concerns. > > Would the Simplified Subsumptions / Deep Subsumptions change have looked > > differently? > > As such I see deprecation cycles as orthogonal to the question if we > > should have breaking > > changes to begin with. > > > > Thus I believe the following: > > > > - Do have a deprecation cycle if possible. > > - Do not treat a deprecation cycle as an excuse. Costs are deferred > > but are as large as ever. > > > > > > should be upgraded to: > > - Preferably _no_ breaking changes. > > - If breaking changes, then with a deprecation cycle, unless technically > > infeasible. > > - An understanding that any breaking change incurs significant costs. > > > > Ocaml recently added multicore support, and they put tremendous effort > > into making > > sure it keeps backwards compatibility: > > https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md > > <https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md> > > > > PS: we should also agree that a "stable" extension should not > > require dependencies on ghc-experimental. To become stable, any > > library support for an extension must move into `base`. > > > > > > This seems like a good idea, however I still remain that _experimental_ > > features should not be on-by-default in a stable compiler. Yes, ideally > > I'd not even see them in a stable compiler, but I know this view is > > contentious. The use of `ghc-experimental` should therefore be guarded > > by `--std=experimental` as Julian suggested. That is a loud opt-in to > > experimental features. > > > > -- > Adam Gundry, Haskell Consultant > Well-Typed LLP, https://www.well-typed.com/ > > Registered in England & Wales, OC335890 > 27 Old Gloucester Street, London WC1N 3AX, England <https://www.google.com/maps/search/27+Old+Gloucester+Street,+London+WC1N+3AX,+England?entry=gmail&source=g> > > _______________________________________________ > ghc-steering-committee mailing list > ghc-steering-committee@haskell.org <mailto:ghc-steering-committee@haskell.org> > https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org <mailto:ghc-steering-committee@haskell.org> https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
Moritz's analysis of why breaking changes are so costly for the whole enterprise is so clarifying; I doubt if there is much that we are considering of more importance. Let me know Moritz if I can help with anything. Chris
On 28 Sep 2023, at 13:39, Moritz Angermann <moritz.angermann@gmail.com> wrote:
Simon,
Thank you for bringing us this far. I'd be happy to step up to drive this further.
I will say that I do see the tension you see as well. And I do believe if we come to a conclusion on this stability policy that it will make GHC development more rigorous, which I think is a good thing for all of us, not just the consumers of the compiler. I think we need to stay mindful that we can still freely experiment on the --std=experimental (or however that flag ends up being named) side. I see this whole discussion as leading us towards the language research reactor side of GHC being primarily confined behind --std=experimental, and the stability seeking (commercial application?) on the other side.
I do not yet see how we can end up with the inability to change. We will just have a clearer process for _breaking_ changes. This does absolutely not mean we have to end up in a local optimum, or that we can not change. We can!
Unless someone speaks up who does _not_ want me to drive, this, I'm happy to start driving this discussion (including writing the proposals, starting next week).
Best, Moritz
On Thu, 28 Sept 2023 at 19:30, Simon Peyton Jones <simon.peytonjones@gmail.com <mailto:simon.peytonjones@gmail.com>> wrote:
Should we have a document (or better spreadsheet?) with a bullet point for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
I think that would be a helpful way to "ground" the discussion a bit more. (The spreadsheet should also give a preliminary classification of extensions, at least into stable/experimental.)
I'm running out of capacity to drive this debate, useful though it is. Does anyone else feel able to drive some of the legwork?
So far this is all informal committee discussion. The next step would be a GHC Proposal inviting broader feedback from the community. I'm just hoping that by debugging it between ourselves we can side-step some unproductive discussions in that bigger context.
I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable
There is a tension here. If we say something is "stable" then we have to be super-careful about changing it. (That's the whole point.) And yet if the feature (like INCOHERENT) is a flaky "you are on your own" unsafePerformIO-like feature, I am axious about tying ourselves into an inability to change the behaviour of corner cases. I'm not sure how to resolve this tension.
Simon
On Thu, 28 Sept 2023 at 02:20, Moritz Angermann <moritz.angermann@gmail.com <mailto:moritz.angermann@gmail.com>> wrote:
I think we are moving in the right direction! I do see however the tension rising on (2). And without being clear about (2), I don’t think we can properly agree on (1). We can agree on (1) in principle, but we need to clarify what we consider unstable/experimental, as a precondition to have finale agreement on (1). Otherwise people might agree to (1), only to be surprised by (2). For (3), I’d be happy to try to get my employer to provide resources for the implementation of —std=experimental.
Thusly I believe we should start to build a list of features we consider sufficiently experimental that they should preclude an existing Haskell program from being considered stable. This list for me contains so far:
- Linear Types - Dependent Haskell
Adam pointed out experimental backend and non-tire-1 platforms. I tend to agree with this, but see this distinctly separate from the language stability (outside of backend specific language extensions, e.g. JSFFI).
Platforms/backends may be experimental but those are (safe for specific lang exts) orthogonal to the Haskell code the compiler accepts.
Should we have a document (or better spreadsheet?) with a bullet point for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
Best, Moritz
On Wed, 27 Sep 2023 at 10:35 PM, Simon Peyton Jones <simon.peytonjones@gmail.com <mailto:simon.peytonjones@gmail.com>> wrote:
it's essential that we continue to have these discussions to ensure we're making the best decisions for the project and our community.
Yes exactly! Its tricky and nuanced; hence trying to articulate something in a concrete doc, so we are all on the same page (literally!).
However, deprecation cycles don't mean we're averse to major changes. It means we introduce them responsibly. When we believe a superior design is possible, we can start a deprecation process to transition towards it.
I have tried to make this explicit in Section 4. See what you think.
I think there are three phases Agree this document. Is it what we want. Categorise extensions into stable/experimental, and identify experimental language features. Implement --std=experimental (Section 6). (1) is what we are doing now. (2) will be some work, done by us. (3) is a larger task: it will require significant work to implement, and may impose unwelcome churn of its own. But that should not stop us doing (1) and (2).
Simon
On Wed, 27 Sept 2023 at 10:20, Moritz Angermann <moritz.angermann@gmail.com <mailto:moritz.angermann@gmail.com>> wrote:
Dear Adam,
Thank you for your thoughtful feedback. I understand your reservations, and it's essential that we continue to have these discussions to ensure we're making the best decisions for the project and our community. Let me address each of your points in turn:
- Cognitive Overhead for Users: I understand the concern about cognitive overhead due to the inability to remove complexity. However, our primary intention is to ensure a gradual transition for our users rather than abrupt shifts. Introducing changes via deprecation cycles allows users to adjust to modifications over time, reducing the immediate cognitive load. It's a balance between stability and simplicity, and I believe this approach allows us still to reduce complexity.
- Maintenance Burden in the Compiler: Maintaining backward compatibility does indeed introduce some overhead. Still, it also encourages a more disciplined and considered approach to changes. With our deprecation cycles in place, it's not that we never remove complexity; rather, we do it in a way that provides ample time for adjustments. This benefits both the development team and the community.
- Risk of Local Optimum: This is a valid concern. However, deprecation cycles don't mean we're averse to major changes. It means we introduce them responsibly. When we believe a superior design is possible, we can start a deprecation process to transition towards it. The flexibility and duration of our deprecation cycles can be tailored depending on the severity of the breaking change.
- Discouraging Volunteer Contributors: I understand that lengthy approval processes can be off-putting. But it's crucial to note that a rigorous process ensures the consistency and reliability of our project. We always welcome and value contributions. Moreover, I believe this stability policy will provide us with clear guardrails on how changes can be contributed.
I will not disagree on the costs. I do believe though that the costs for _breaking_ changes in the compiler ought to be borne by the people making the change, instead of those who use the compiler (and may not even benefit of those changes that caused breakage). I also see the team maintaining GHC as the one to enforce this; they are the ones who cut the releases. The fact that we may have breaking changes due to _bugs_ is covered explicitly in the stability policy document.
With my CLC hat on, I have been focusing on the same stability guidelines as well (if it breaks existing code, I have been against those changes without deprecation policies). The issues with the template-haskell, and ghc library are noted. For the ghc library the question will remain if we intent to provide a stable api to the compiler or not. I believe many tools would like to have one, and if we relegate anything unstable to ghc-experimental this might be achieved. For template-haskell this is a bigger concern. Maybe we can collectively come up with a solution that would allow us to provide a more insulated template haskell interface from the compiler.
However for template-haskell we might also need to look at what exactly caused those breaking changes in the past.
What this document outlines (in my understanding) is that any experimental feature development can _only_ be visible behind --std=experimental, and the dependency of ghc-experimental. Unless those are given, the compiler should accept existing programs. This should allow us enough room to innovate (everyone is always free to opt-in to bleeding edge features with --std=experimental). I also believe that most of what we have today will need to be treated as non-experimental simply because we did not have that mechanism before. We don't want to break existing programs as much as possible, thus relegating existing features into --std=experimental (except for some fairly clear ones: e.g. Dependent Haskell, and Linear Types?) is not really possible. What we can however do is start deprecation phases for a few versions, moving features we consider highly experimental (or maybe even bad) into `--std=experimental`. Just by having deprecation phases and given the ecosystem enough time to adjust (and provide feedback) we might come to different conclusions.
As I've also outlined in the document, _if_ GHC was trivially swappable, companies like IOG would _love_ to try new compilers and report back bugs and regressions. As it is today, we can't. Making a large live codebase compatible with 9.8 is a multiple weeks effort. Experimenting with nightlies is technically impossible. _If_ I could setup the built of our software trivial with ghc nightlies, I'd be _happy_ to build the infrastructure out it to provide performance regressions (compilation, runtime, ...) for our codebase and provide the feedback to the GHC team; however I can't. And thus I'm stuck patching and fixing 8.10, and 9.2 today. 9.6 maybe soon, but likely at the point in time where 9.6 is not going to see any further releases, so I can spare trying to even forward port my patches to HEAD. Not that I could even test them with head properly, as our source is not accepted by HEAD. Thus I end up writing patches against old stale branches. This to me is a fairly big discouragement from contributing to GHC.
Best, Moritz
On Mon, 25 Sept 2023 at 15:17, Adam Gundry <adam@well-typed.com <mailto:adam@well-typed.com>> wrote:
I'm afraid that I'm somewhat sceptical of this approach.
A strong stability guarantee is certainly a valuable goal, but it also comes with costs, which I'd like to see more clearly articulated. Some of them include:
* Cognitive overhead for users, because of the inability to remove complexity from the design.
* Increasing maintenance burden in the compiler, because of the additional work needed to implement new features and the inability to remove complexity from the implementation.
* A risk of getting stuck in a local optimum, because moving to a better design would entail breaking changes.
* Discouraging volunteer contributors, who are much less likely to work on a potentially beneficial change if the process for getting it approved is too onerous. (I'm worried we're already reaching that point due to the increasing burden of well-intentioned processes.)
Ultimately every proposed change has a cost-benefit trade-off, with risk of breakage being one of the costs. We need to consciously evaluate that trade-off on a case-by-case basis. Almost all changes might break something (e.g. by regressing performance, or for Hyrum's Law reasons), so there needs to be a proportionate assessment of how likely each change is to be damaging in practice, bearing in mind that such an assessment is itself costly and limited in scope.
It seems to me that the GHC team have taken on board lessons regarding stability of the language, and the extension system already gives quite a lot of flexibility to evolve the language in a backwards-compatible way. In my experience, the key stability problems preventing upgrades to recent GHC releases are:
* The cascading effect of breaking changes in one library causing the need to upgrade libraries which depend upon it. This is primarily under the control of the CLC and library maintainers, however, not the GHC team. It would help if base was minimal and reinstallable, but that isn't a total solution either, because you'd still have to worry about packages depending on template-haskell or the ghc package itself.
* Performance regressions or critical bugs. These tend to be a significant obstacle to upgrading for smaller commercial users. But spending more of our limited resources on stability of the language means fewer resources for resolving these issues.
There's surely more we can do here, but let's be careful not to pay too many costs to achieve stability of the *language* alone, when stability of the *libraries* and *implementation* are both more important and harder to fix.
Adam
On 22/09/2023 10:53, Simon Peyton Jones wrote: > Dear GHC SC > > To avoid derailing the debate about -Wsevere > <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, and HasField redesign <https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, I'm starting a new (email for now) thread about stability. > > I have tried to articulate what I believe is an evolving consensus in > this document > <https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47ZulgaZds/edit?usp=sharing>. > > If we converge, we'll turn that into a proper PR for the GHC proposal > process, although it has wider implications than just GHC proposals and > we should share with a broader audience. But let's start with the > steering committee. > > Any views? You all have edit rights. > > I think that the draft covers Moritz's and Julian's goals, at least that > was my intention. I have pasted Moritz's last email below, for context. > > Simon > > > ========= Moritz's last email ============ > > Now, this is derailing the original discussion a bit, and I'm not sure > how far we want to take this. But, regarding @Simon Marlow > <mailto:marlowsd@gmail.com <mailto:marlowsd@gmail.com>>'s comment > > This is one cultural aspect of our community I'd like to shift: the > expectation that it's OK to make breaking changes as long as you > warn about > them or go through a migration cycle. It just isn't! (and I speak as > someone who used to make lots of changes, I'm now fully repentant!). > That's > not to say that we shouldn't ever change anything, but when > considering the > cost/benefit tradeoff adding a migration cycle doesn't reduce the > cost, it > just defers it. > > > I actually read this as we should stop having breaking changes to begin > with. And _if_ we > do have breaking changes, that deprecation does not change the need to > actually change > code (cost). As outlined in my reply to that, and @Richard Eisenberg > <mailto:lists@richarde.dev <mailto:lists@richarde.dev>>'s observation, it > "smears" the cost. The--to me--_much_ bigger implication of deprecation > cycles is that we > _inform_ our _customers_ about upcoming changes _early_, instead of > _after the fact_. We > also give them ample time to react. Being by changing their code, or > raising their concerns. > Would the Simplified Subsumptions / Deep Subsumptions change have looked > differently? > As such I see deprecation cycles as orthogonal to the question if we > should have breaking > changes to begin with. > > Thus I believe the following: > > - Do have a deprecation cycle if possible. > - Do not treat a deprecation cycle as an excuse. Costs are deferred > but are as large as ever. > > > should be upgraded to: > - Preferably _no_ breaking changes. > - If breaking changes, then with a deprecation cycle, unless technically > infeasible. > - An understanding that any breaking change incurs significant costs. > > Ocaml recently added multicore support, and they put tremendous effort > into making > sure it keeps backwards compatibility: > https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md > <https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md> > > PS: we should also agree that a "stable" extension should not > require dependencies on ghc-experimental. To become stable, any > library support for an extension must move into `base`. > > > This seems like a good idea, however I still remain that _experimental_ > features should not be on-by-default in a stable compiler. Yes, ideally > I'd not even see them in a stable compiler, but I know this view is > contentious. The use of `ghc-experimental` should therefore be guarded > by `--std=experimental` as Julian suggested. That is a loud opt-in to > experimental features. >
-- Adam Gundry, Haskell Consultant Well-Typed LLP, https://www.well-typed.com/
Registered in England & Wales, OC335890 27 Old Gloucester Street, London WC1N 3AX, England <https://www.google.com/maps/search/27+Old+Gloucester+Street,+London+WC1N+3AX,+England?entry=gmail&source=g>
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org <mailto:ghc-steering-committee@haskell.org> https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
ghc-steering-committee mailing list ghc-steering-committee@haskell.org <mailto:ghc-steering-committee@haskell.org> https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
Thank you for bringing us this far. I'd be happy to step up to drive this further.
Thank you Moritz, that would be very helpful. I see the steps (*not *in dependency order) including - Develop stability ideas for Template Haskell. I think we have agreed that it's a tricky case: widely used, but hard to stabilise - Develop a preliminary classification of language extensions, in partnership with the folk (who include Adam) working on the extension life cycle proposal <https://github.com/ghc-proposals/ghc-proposals/pull/601>. The preliminary spreadsheet <https://docs.google.com/spreadsheets/d/1sRIcNKdflX2ogrx2EF3vKOn0vmv-UEOdladBqtYXdaw/edit#gid=0>is helpful -- thank you Adam. Let's not duplicate this work! - Ditto for "experimental features". - Turn the Google doc into a GHC Proposal. I see all this as the GHC counterpart to the GHC base-library proposal <https://github.com/haskellfoundation/tech-proposals/blob/main/proposals/accepted/051-ghc-base-libraries.rst>: our general goal is to make a clear boundary between "stable" and "experimental", so that: - users know when they are moving into experimental land - developers know when they risk breaking stable code While the boundary is unclear, misunderstandings arise in both directions. Simon On Thu, 28 Sept 2023 at 13:39, Moritz Angermann <moritz.angermann@gmail.com> wrote:
Simon,
Thank you for bringing us this far. I'd be happy to step up to drive this further.
I will say that I do see the tension you see as well. And I do believe if we come to a conclusion on this stability policy that it will make GHC development more rigorous, which I think is a good thing for all of us, not just the consumers of the compiler. I think we need to stay mindful that we can still freely experiment on the --std=experimental (or however that flag ends up being named) side. I see this whole discussion as leading us towards the language research reactor side of GHC being primarily confined behind --std=experimental, and the stability seeking (commercial application?) on the other side.
I do not yet see how we can end up with the inability to change. We will just have a clearer process for _breaking_ changes. This does absolutely not mean we have to end up in a local optimum, or that we can not change. We can!
Unless someone speaks up who does _not_ want me to drive, this, I'm happy to start driving this discussion (including writing the proposals, starting next week).
Best, Moritz
On Thu, 28 Sept 2023 at 19:30, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Should we have a document (or better spreadsheet?) with a bullet point
for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
I think that would be a helpful way to "ground" the discussion a bit more. (The spreadsheet should also give a preliminary classification of extensions, at least into stable/experimental.)
I'm running out of capacity to drive this debate, useful though it is. Does anyone else feel able to drive some of the legwork?
So far this is all informal committee discussion. The next step would be a GHC Proposal inviting broader feedback from the community. I'm just hoping that by debugging it between ourselves we can side-step some unproductive discussions in that bigger context.
I believe we need to take into account that we can’t end up classifying
most of todays Haskell programs unstable
There is a tension here. If we say something is "stable" then we have to be super-careful about changing it. (That's the whole point.) And yet if the feature (like INCOHERENT) is a flaky "you are on your own" unsafePerformIO-like feature, I am axious about tying ourselves into an inability to change the behaviour of corner cases. I'm not sure how to resolve this tension.
Simon
On Thu, 28 Sept 2023 at 02:20, Moritz Angermann < moritz.angermann@gmail.com> wrote:
I think we are moving in the right direction! I do see however the tension rising on (2). And without being clear about (2), I don’t think we can properly agree on (1). We can agree on (1) in principle, but we need to clarify what we consider unstable/experimental, as a precondition to have finale agreement on (1). Otherwise people might agree to (1), only to be surprised by (2). For (3), I’d be happy to try to get my employer to provide resources for the implementation of —std=experimental.
Thusly I believe we should start to build a list of features we consider sufficiently experimental that they should preclude an existing Haskell program from being considered stable. This list for me contains so far:
- Linear Types - Dependent Haskell
Adam pointed out experimental backend and non-tire-1 platforms. I tend to agree with this, but see this distinctly separate from the language stability (outside of backend specific language extensions, e.g. JSFFI).
Platforms/backends may be experimental but those are (safe for specific lang exts) orthogonal to the Haskell code the compiler accepts.
Should we have a document (or better spreadsheet?) with a bullet point for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
Best, Moritz
On Wed, 27 Sep 2023 at 10:35 PM, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
it's essential that we continue to have these discussions to ensure
we're making the best decisions for the project and our community.
Yes exactly! Its tricky and nuanced; hence trying to articulate something in a concrete doc, so we are all on the same page (literally!).
However, deprecation cycles don't mean we're averse to major changes.
It means we introduce them responsibly. When we believe a superior design is possible, we can start a deprecation process to transition towards it.
I have tried to make this explicit in Section 4. See what you think.
I think there are three phases
1. Agree this document. Is it what we want. 2. Categorise extensions into stable/experimental, and identify experimental language features. 3. Implement --std=experimental (Section 6).
(1) is what we are doing now. (2) will be some work, done by us. (3) is a larger task: it will require significant work to implement, and may impose unwelcome churn of its own. But that should not stop us doing (1) and (2).
Simon
-
On Wed, 27 Sept 2023 at 10:20, Moritz Angermann < moritz.angermann@gmail.com> wrote:
Dear Adam,
Thank you for your thoughtful feedback. I understand your reservations, and it's essential that we continue to have these discussions to ensure we're making the best decisions for the project and our community. Let me address each of your points in turn: - Cognitive Overhead for Users: I understand the concern about cognitive overhead due to the inability to remove complexity. However, our primary intention is to ensure a gradual transition for our users rather than abrupt shifts. Introducing changes via deprecation cycles allows users to adjust to modifications over time, reducing the immediate cognitive load. It's a balance between stability and simplicity, and I believe this approach allows us still to reduce complexity.
- Maintenance Burden in the Compiler: Maintaining backward compatibility does indeed introduce some overhead. Still, it also encourages a more disciplined and considered approach to changes. With our deprecation cycles in place, it's not that we never remove complexity; rather, we do it in a way that provides ample time for adjustments. This benefits both the development team and the community.
- Risk of Local Optimum: This is a valid concern. However, deprecation cycles don't mean we're averse to major changes. It means we introduce them responsibly. When we believe a superior design is possible, we can start a deprecation process to transition towards it. The flexibility and duration of our deprecation cycles can be tailored depending on the severity of the breaking change.
- Discouraging Volunteer Contributors: I understand that lengthy approval processes can be off-putting. But it's crucial to note that a rigorous process ensures the consistency and reliability of our project. We always welcome and value contributions. Moreover, I believe this stability policy will provide us with clear guardrails on how changes can be contributed.
I will not disagree on the costs. I do believe though that the costs for _breaking_ changes in the compiler ought to be borne by the people making the change, instead of those who use the compiler (and may not even benefit of those changes that caused breakage). I also see the team maintaining GHC as the one to enforce this; they are the ones who cut the releases. The fact that we may have breaking changes due to _bugs_ is covered explicitly in the stability policy document.
With my CLC hat on, I have been focusing on the same stability guidelines as well (if it breaks existing code, I have been against those changes without deprecation policies). The issues with the template-haskell, and ghc library are noted. For the ghc library the question will remain if we intent to provide a stable api to the compiler or not. I believe many tools would like to have one, and if we relegate anything unstable to ghc-experimental this might be achieved. For template-haskell this is a bigger concern. Maybe we can collectively come up with a solution that would allow us to provide a more insulated template haskell interface from the compiler.
However for template-haskell we might also need to look at what exactly caused those breaking changes in the past.
What this document outlines (in my understanding) is that any experimental feature development can _only_ be visible behind --std=experimental, and the dependency of ghc-experimental. Unless those are given, the compiler should accept existing programs. This should allow us enough room to innovate (everyone is always free to opt-in to bleeding edge features with --std=experimental). I also believe that most of what we have today will need to be treated as non-experimental simply because we did not have that mechanism before. We don't want to break existing programs as much as possible, thus relegating existing features into --std=experimental (except for some fairly clear ones: e.g. Dependent Haskell, and Linear Types?) is not really possible. What we can however do is start deprecation phases for a few versions, moving features we consider highly experimental (or maybe even bad) into `--std=experimental`. Just by having deprecation phases and given the ecosystem enough time to adjust (and provide feedback) we might come to different conclusions.
As I've also outlined in the document, _if_ GHC was trivially swappable, companies like IOG would _love_ to try new compilers and report back bugs and regressions. As it is today, we can't. Making a large live codebase compatible with 9.8 is a multiple weeks effort. Experimenting with nightlies is technically impossible. _If_ I could setup the built of our software trivial with ghc nightlies, I'd be _happy_ to build the infrastructure out it to provide performance regressions (compilation, runtime, ...) for our codebase and provide the feedback to the GHC team; however I can't. And thus I'm stuck patching and fixing 8.10, and 9.2 today. 9.6 maybe soon, but likely at the point in time where 9.6 is not going to see any further releases, so I can spare trying to even forward port my patches to HEAD. Not that I could even test them with head properly, as our source is not accepted by HEAD. Thus I end up writing patches against old stale branches. This to me is a fairly big discouragement from contributing to GHC.
Best, Moritz
On Mon, 25 Sept 2023 at 15:17, Adam Gundry <adam@well-typed.com> wrote:
I'm afraid that I'm somewhat sceptical of this approach.
A strong stability guarantee is certainly a valuable goal, but it also comes with costs, which I'd like to see more clearly articulated. Some of them include:
* Cognitive overhead for users, because of the inability to remove complexity from the design.
* Increasing maintenance burden in the compiler, because of the additional work needed to implement new features and the inability to remove complexity from the implementation.
* A risk of getting stuck in a local optimum, because moving to a better design would entail breaking changes.
* Discouraging volunteer contributors, who are much less likely to work on a potentially beneficial change if the process for getting it approved is too onerous. (I'm worried we're already reaching that point due to the increasing burden of well-intentioned processes.)
Ultimately every proposed change has a cost-benefit trade-off, with risk of breakage being one of the costs. We need to consciously evaluate that trade-off on a case-by-case basis. Almost all changes might break something (e.g. by regressing performance, or for Hyrum's Law reasons), so there needs to be a proportionate assessment of how likely each change is to be damaging in practice, bearing in mind that such an assessment is itself costly and limited in scope.
It seems to me that the GHC team have taken on board lessons regarding stability of the language, and the extension system already gives quite a lot of flexibility to evolve the language in a backwards-compatible way. In my experience, the key stability problems preventing upgrades to recent GHC releases are:
* The cascading effect of breaking changes in one library causing the need to upgrade libraries which depend upon it. This is primarily under the control of the CLC and library maintainers, however, not the GHC team. It would help if base was minimal and reinstallable, but that isn't a total solution either, because you'd still have to worry about packages depending on template-haskell or the ghc package itself.
* Performance regressions or critical bugs. These tend to be a significant obstacle to upgrading for smaller commercial users. But spending more of our limited resources on stability of the language means fewer resources for resolving these issues.
There's surely more we can do here, but let's be careful not to pay too many costs to achieve stability of the *language* alone, when stability of the *libraries* and *implementation* are both more important and harder to fix.
Adam
On 22/09/2023 10:53, Simon Peyton Jones wrote: > Dear GHC SC > > To avoid derailing the debate about -Wsevere > < https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, and HasField redesign < https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, I'm starting a new (email for now) thread about stability. > > I have tried to articulate what I believe is an evolving consensus in > this document > < https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47Zulga... >. > > If we converge, we'll turn that into a proper PR for the GHC proposal > process, although it has wider implications than just GHC proposals and > we should share with a broader audience. But let's start with the > steering committee. > > Any views? You all have edit rights. > > I think that the draft covers Moritz's and Julian's goals, at least that > was my intention. I have pasted Moritz's last email below, for context. > > Simon > > > ========= Moritz's last email ============ > > Now, this is derailing the original discussion a bit, and I'm not sure > how far we want to take this. But, regarding @Simon Marlow > <mailto:marlowsd@gmail.com>'s comment > > This is one cultural aspect of our community I'd like to shift: the > expectation that it's OK to make breaking changes as long as you > warn about > them or go through a migration cycle. It just isn't! (and I speak as > someone who used to make lots of changes, I'm now fully repentant!). > That's > not to say that we shouldn't ever change anything, but when > considering the > cost/benefit tradeoff adding a migration cycle doesn't reduce the > cost, it > just defers it. > > > I actually read this as we should stop having breaking changes to begin > with. And _if_ we > do have breaking changes, that deprecation does not change the need to > actually change > code (cost). As outlined in my reply to that, and @Richard Eisenberg > <mailto:lists@richarde.dev>'s observation, it > "smears" the cost. The--to me--_much_ bigger implication of deprecation > cycles is that we > _inform_ our _customers_ about upcoming changes _early_, instead of > _after the fact_. We > also give them ample time to react. Being by changing their code, or > raising their concerns. > Would the Simplified Subsumptions / Deep Subsumptions change have looked > differently? > As such I see deprecation cycles as orthogonal to the question if we > should have breaking > changes to begin with. > > Thus I believe the following: > > - Do have a deprecation cycle if possible. > - Do not treat a deprecation cycle as an excuse. Costs are deferred > but are as large as ever. > > > should be upgraded to: > - Preferably _no_ breaking changes. > - If breaking changes, then with a deprecation cycle, unless technically > infeasible. > - An understanding that any breaking change incurs significant costs. > > Ocaml recently added multicore support, and they put tremendous effort > into making > sure it keeps backwards compatibility: > https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md > < https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md> > > PS: we should also agree that a "stable" extension should not > require dependencies on ghc-experimental. To become stable, any > library support for an extension must move into `base`. > > > This seems like a good idea, however I still remain that _experimental_ > features should not be on-by-default in a stable compiler. Yes, ideally > I'd not even see them in a stable compiler, but I know this view is > contentious. The use of `ghc-experimental` should therefore be guarded > by `--std=experimental` as Julian suggested. That is a loud opt-in to > experimental features. >
-- Adam Gundry, Haskell Consultant Well-Typed LLP, https://www.well-typed.com/
Registered in England & Wales, OC335890 27 Old Gloucester Street, London WC1N 3AX, England <https://www.google.com/maps/search/27+Old+Gloucester+Street,+London+WC1N+3AX,+England?entry=gmail&source=g>
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org
https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org
https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
Simon, Over the weekend, I've given this considerable thought and decided to approach it from a slightly different angle. I concur that we shouldn't duplicate or replace any existing work. I'm especially appreciative of Adam pointing out the current spreadsheet. Such insights highlight the value of our discussions! My plan right now is as follows: 1. *GHC Experimental Proposal*: I'll draft a proposal for --ghc=experimental. While it won't mark anything as experimental immediately, it sets the groundwork for distinguishing between experimental and stable features. This will also help us introduce experimental features with a clear flag from the outset. 2. *Extension Life Cycle Discussion*: I'll reconnect with Adam and others regarding the extension life cycle proposal. The core idea of having a clear life cycle for extensions seems to be well-received. The nuances and details are what sparked our initial conversation. 3. *Marking Features as Experimental*: I plan to propose marking JavaScriptFFI, Linear Types, and Dependent Haskell as experimental for the time being. We'll gauge the community's response and gather feedback from the original authors during the proposal process. 4. *Stability Policy Proposal*: Based on our collective input, I'll draft a proposal centered on the stability policy. With (1) and (2), I believe we are in a good position to take the GHC Extensions sheet (and also add GHC Features), and start moving them through the life-cycle into experimental features? Additionally, I'll be: - Reviewing prior work on template-haskell. - Exploring ways to make more libraries re-installable. Lastly, let's not lose sight of: - The Stability Working Group. - The GHC API Stability initiative from the HF. Best, Moritz On Fri, 29 Sept 2023 at 17:53, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Thank you for bringing us this far. I'd be happy to step up to drive this
further.
Thank you Moritz, that would be very helpful. I see the steps (*not *in dependency order) including
- Develop stability ideas for Template Haskell. I think we have agreed that it's a tricky case: widely used, but hard to stabilise - Develop a preliminary classification of language extensions, in partnership with the folk (who include Adam) working on the extension life cycle proposal <https://github.com/ghc-proposals/ghc-proposals/pull/601>. The preliminary spreadsheet <https://docs.google.com/spreadsheets/d/1sRIcNKdflX2ogrx2EF3vKOn0vmv-UEOdladBqtYXdaw/edit#gid=0>is helpful -- thank you Adam. Let's not duplicate this work! - Ditto for "experimental features". - Turn the Google doc into a GHC Proposal.
I see all this as the GHC counterpart to the GHC base-library proposal <https://github.com/haskellfoundation/tech-proposals/blob/main/proposals/accepted/051-ghc-base-libraries.rst>: our general goal is to make a clear boundary between "stable" and "experimental", so that:
- users know when they are moving into experimental land - developers know when they risk breaking stable code
While the boundary is unclear, misunderstandings arise in both directions.
Simon
On Thu, 28 Sept 2023 at 13:39, Moritz Angermann < moritz.angermann@gmail.com> wrote:
Simon,
Thank you for bringing us this far. I'd be happy to step up to drive this further.
I will say that I do see the tension you see as well. And I do believe if we come to a conclusion on this stability policy that it will make GHC development more rigorous, which I think is a good thing for all of us, not just the consumers of the compiler. I think we need to stay mindful that we can still freely experiment on the --std=experimental (or however that flag ends up being named) side. I see this whole discussion as leading us towards the language research reactor side of GHC being primarily confined behind --std=experimental, and the stability seeking (commercial application?) on the other side.
I do not yet see how we can end up with the inability to change. We will just have a clearer process for _breaking_ changes. This does absolutely not mean we have to end up in a local optimum, or that we can not change. We can!
Unless someone speaks up who does _not_ want me to drive, this, I'm happy to start driving this discussion (including writing the proposals, starting next week).
Best, Moritz
On Thu, 28 Sept 2023 at 19:30, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Should we have a document (or better spreadsheet?) with a bullet point
for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
I think that would be a helpful way to "ground" the discussion a bit more. (The spreadsheet should also give a preliminary classification of extensions, at least into stable/experimental.)
I'm running out of capacity to drive this debate, useful though it is. Does anyone else feel able to drive some of the legwork?
So far this is all informal committee discussion. The next step would be a GHC Proposal inviting broader feedback from the community. I'm just hoping that by debugging it between ourselves we can side-step some unproductive discussions in that bigger context.
I believe we need to take into account that we can’t end up classifying
most of todays Haskell programs unstable
There is a tension here. If we say something is "stable" then we have to be super-careful about changing it. (That's the whole point.) And yet if the feature (like INCOHERENT) is a flaky "you are on your own" unsafePerformIO-like feature, I am axious about tying ourselves into an inability to change the behaviour of corner cases. I'm not sure how to resolve this tension.
Simon
On Thu, 28 Sept 2023 at 02:20, Moritz Angermann < moritz.angermann@gmail.com> wrote:
I think we are moving in the right direction! I do see however the tension rising on (2). And without being clear about (2), I don’t think we can properly agree on (1). We can agree on (1) in principle, but we need to clarify what we consider unstable/experimental, as a precondition to have finale agreement on (1). Otherwise people might agree to (1), only to be surprised by (2). For (3), I’d be happy to try to get my employer to provide resources for the implementation of —std=experimental.
Thusly I believe we should start to build a list of features we consider sufficiently experimental that they should preclude an existing Haskell program from being considered stable. This list for me contains so far:
- Linear Types - Dependent Haskell
Adam pointed out experimental backend and non-tire-1 platforms. I tend to agree with this, but see this distinctly separate from the language stability (outside of backend specific language extensions, e.g. JSFFI).
Platforms/backends may be experimental but those are (safe for specific lang exts) orthogonal to the Haskell code the compiler accepts.
Should we have a document (or better spreadsheet?) with a bullet point for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
Best, Moritz
On Wed, 27 Sep 2023 at 10:35 PM, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
it's essential that we continue to have these discussions to ensure
we're making the best decisions for the project and our community.
Yes exactly! Its tricky and nuanced; hence trying to articulate something in a concrete doc, so we are all on the same page (literally!).
However, deprecation cycles don't mean we're averse to major changes.
It means we introduce them responsibly. When we believe a superior design is possible, we can start a deprecation process to transition towards it.
I have tried to make this explicit in Section 4. See what you think.
I think there are three phases
1. Agree this document. Is it what we want. 2. Categorise extensions into stable/experimental, and identify experimental language features. 3. Implement --std=experimental (Section 6).
(1) is what we are doing now. (2) will be some work, done by us. (3) is a larger task: it will require significant work to implement, and may impose unwelcome churn of its own. But that should not stop us doing (1) and (2).
Simon
-
On Wed, 27 Sept 2023 at 10:20, Moritz Angermann < moritz.angermann@gmail.com> wrote:
Dear Adam,
Thank you for your thoughtful feedback. I understand your reservations, and it's essential that we continue to have these discussions to ensure we're making the best decisions for the project and our community. Let me address each of your points in turn: - Cognitive Overhead for Users: I understand the concern about cognitive overhead due to the inability to remove complexity. However, our primary intention is to ensure a gradual transition for our users rather than abrupt shifts. Introducing changes via deprecation cycles allows users to adjust to modifications over time, reducing the immediate cognitive load. It's a balance between stability and simplicity, and I believe this approach allows us still to reduce complexity.
- Maintenance Burden in the Compiler: Maintaining backward compatibility does indeed introduce some overhead. Still, it also encourages a more disciplined and considered approach to changes. With our deprecation cycles in place, it's not that we never remove complexity; rather, we do it in a way that provides ample time for adjustments. This benefits both the development team and the community.
- Risk of Local Optimum: This is a valid concern. However, deprecation cycles don't mean we're averse to major changes. It means we introduce them responsibly. When we believe a superior design is possible, we can start a deprecation process to transition towards it. The flexibility and duration of our deprecation cycles can be tailored depending on the severity of the breaking change.
- Discouraging Volunteer Contributors: I understand that lengthy approval processes can be off-putting. But it's crucial to note that a rigorous process ensures the consistency and reliability of our project. We always welcome and value contributions. Moreover, I believe this stability policy will provide us with clear guardrails on how changes can be contributed.
I will not disagree on the costs. I do believe though that the costs for _breaking_ changes in the compiler ought to be borne by the people making the change, instead of those who use the compiler (and may not even benefit of those changes that caused breakage). I also see the team maintaining GHC as the one to enforce this; they are the ones who cut the releases. The fact that we may have breaking changes due to _bugs_ is covered explicitly in the stability policy document.
With my CLC hat on, I have been focusing on the same stability guidelines as well (if it breaks existing code, I have been against those changes without deprecation policies). The issues with the template-haskell, and ghc library are noted. For the ghc library the question will remain if we intent to provide a stable api to the compiler or not. I believe many tools would like to have one, and if we relegate anything unstable to ghc-experimental this might be achieved. For template-haskell this is a bigger concern. Maybe we can collectively come up with a solution that would allow us to provide a more insulated template haskell interface from the compiler.
However for template-haskell we might also need to look at what exactly caused those breaking changes in the past.
What this document outlines (in my understanding) is that any experimental feature development can _only_ be visible behind --std=experimental, and the dependency of ghc-experimental. Unless those are given, the compiler should accept existing programs. This should allow us enough room to innovate (everyone is always free to opt-in to bleeding edge features with --std=experimental). I also believe that most of what we have today will need to be treated as non-experimental simply because we did not have that mechanism before. We don't want to break existing programs as much as possible, thus relegating existing features into --std=experimental (except for some fairly clear ones: e.g. Dependent Haskell, and Linear Types?) is not really possible. What we can however do is start deprecation phases for a few versions, moving features we consider highly experimental (or maybe even bad) into `--std=experimental`. Just by having deprecation phases and given the ecosystem enough time to adjust (and provide feedback) we might come to different conclusions.
As I've also outlined in the document, _if_ GHC was trivially swappable, companies like IOG would _love_ to try new compilers and report back bugs and regressions. As it is today, we can't. Making a large live codebase compatible with 9.8 is a multiple weeks effort. Experimenting with nightlies is technically impossible. _If_ I could setup the built of our software trivial with ghc nightlies, I'd be _happy_ to build the infrastructure out it to provide performance regressions (compilation, runtime, ...) for our codebase and provide the feedback to the GHC team; however I can't. And thus I'm stuck patching and fixing 8.10, and 9.2 today. 9.6 maybe soon, but likely at the point in time where 9.6 is not going to see any further releases, so I can spare trying to even forward port my patches to HEAD. Not that I could even test them with head properly, as our source is not accepted by HEAD. Thus I end up writing patches against old stale branches. This to me is a fairly big discouragement from contributing to GHC.
Best, Moritz
On Mon, 25 Sept 2023 at 15:17, Adam Gundry <adam@well-typed.com> wrote:
> I'm afraid that I'm somewhat sceptical of this approach. > > A strong stability guarantee is certainly a valuable goal, but it > also > comes with costs, which I'd like to see more clearly articulated. > Some > of them include: > > * Cognitive overhead for users, because of the inability to remove > complexity from the design. > > * Increasing maintenance burden in the compiler, because of the > additional work needed to implement new features and the inability > to > remove complexity from the implementation. > > * A risk of getting stuck in a local optimum, because moving to a > better design would entail breaking changes. > > * Discouraging volunteer contributors, who are much less likely to > work on a potentially beneficial change if the process for getting > it > approved is too onerous. (I'm worried we're already reaching that > point > due to the increasing burden of well-intentioned processes.) > > Ultimately every proposed change has a cost-benefit trade-off, with > risk > of breakage being one of the costs. We need to consciously evaluate > that > trade-off on a case-by-case basis. Almost all changes might break > something (e.g. by regressing performance, or for Hyrum's Law > reasons), > so there needs to be a proportionate assessment of how likely each > change is to be damaging in practice, bearing in mind that such an > assessment is itself costly and limited in scope. > > It seems to me that the GHC team have taken on board lessons > regarding > stability of the language, and the extension system already gives > quite > a lot of flexibility to evolve the language in a > backwards-compatible > way. In my experience, the key stability problems preventing > upgrades to > recent GHC releases are: > > * The cascading effect of breaking changes in one library causing > the > need to upgrade libraries which depend upon it. This is primarily > under > the control of the CLC and library maintainers, however, not the GHC > team. It would help if base was minimal and reinstallable, but that > isn't a total solution either, because you'd still have to worry > about > packages depending on template-haskell or the ghc package itself. > > * Performance regressions or critical bugs. These tend to be a > significant obstacle to upgrading for smaller commercial users. But > spending more of our limited resources on stability of the language > means fewer resources for resolving these issues. > > There's surely more we can do here, but let's be careful not to pay > too > many costs to achieve stability of the *language* alone, when > stability > of the *libraries* and *implementation* are both more important and > harder to fix. > > Adam > > > On 22/09/2023 10:53, Simon Peyton Jones wrote: > > Dear GHC SC > > > > To avoid derailing the debate about -Wsevere > > < > https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, > and HasField redesign < > https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, > I'm starting a new (email for now) thread about stability. > > > > I have tried to articulate what I believe is an evolving consensus > in > > this document > > < > https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47Zulga... > >. > > > > If we converge, we'll turn that into a proper PR for the GHC > proposal > > process, although it has wider implications than just GHC > proposals and > > we should share with a broader audience. But let's start with the > > steering committee. > > > > Any views? You all have edit rights. > > > > I think that the draft covers Moritz's and Julian's goals, at > least that > > was my intention. I have pasted Moritz's last email below, for > context. > > > > Simon > > > > > > ========= Moritz's last email ============ > > > > Now, this is derailing the original discussion a bit, and I'm not > sure > > how far we want to take this. But, regarding @Simon Marlow > > <mailto:marlowsd@gmail.com>'s comment > > > > This is one cultural aspect of our community I'd like to > shift: the > > expectation that it's OK to make breaking changes as long as > you > > warn about > > them or go through a migration cycle. It just isn't! (and I > speak as > > someone who used to make lots of changes, I'm now fully > repentant!). > > That's > > not to say that we shouldn't ever change anything, but when > > considering the > > cost/benefit tradeoff adding a migration cycle doesn't reduce > the > > cost, it > > just defers it. > > > > > > I actually read this as we should stop having breaking changes to > begin > > with. And _if_ we > > do have breaking changes, that deprecation does not change the > need to > > actually change > > code (cost). As outlined in my reply to that, and @Richard > Eisenberg > > <mailto:lists@richarde.dev>'s observation, it > > "smears" the cost. The--to me--_much_ bigger implication of > deprecation > > cycles is that we > > _inform_ our _customers_ about upcoming changes _early_, instead > of > > _after the fact_. We > > also give them ample time to react. Being by changing their code, > or > > raising their concerns. > > Would the Simplified Subsumptions / Deep Subsumptions change > have looked > > differently? > > As such I see deprecation cycles as orthogonal to the question if > we > > should have breaking > > changes to begin with. > > > > Thus I believe the following: > > > > - Do have a deprecation cycle if possible. > > - Do not treat a deprecation cycle as an excuse. Costs are > deferred > > but are as large as ever. > > > > > > should be upgraded to: > > - Preferably _no_ breaking changes. > > - If breaking changes, then with a deprecation cycle, unless > technically > > infeasible. > > - An understanding that any breaking change incurs significant > costs. > > > > Ocaml recently added multicore support, and they put tremendous > effort > > into making > > sure it keeps backwards compatibility: > > > https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md > > < > https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md> > > > > PS: we should also agree that a "stable" extension should not > > require dependencies on ghc-experimental. To become stable, > any > > library support for an extension must move into `base`. > > > > > > This seems like a good idea, however I still remain that > _experimental_ > > features should not be on-by-default in a stable compiler. Yes, > ideally > > I'd not even see them in a stable compiler, but I know this view > is > > contentious. The use of `ghc-experimental` should therefore be > guarded > > by `--std=experimental` as Julian suggested. That is a loud opt-in > to > > experimental features. > > > > -- > Adam Gundry, Haskell Consultant > Well-Typed LLP, https://www.well-typed.com/ > > Registered in England & Wales, OC335890 > 27 Old Gloucester Street, London WC1N 3AX, England > <https://www.google.com/maps/search/27+Old+Gloucester+Street,+London+WC1N+3AX,+England?entry=gmail&source=g> > > _______________________________________________ > ghc-steering-committee mailing list > ghc-steering-committee@haskell.org > > https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee > _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org
https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
I find it difficult to follow this conversation. It's a little overwhelming to me. So I don't have much to contribute. I have a thought though. Part of what gives the feeling of instability that GHC has an aura for is that haskellers are habituated to use dozens of extensions for normal programs. It makes the act of adding an extension banal, where it shouldn't. It probably doesn't matter how many options, warnings, explicit bold text in documentation we add: the single best move that we can do to promote stability in Haskell is to make it possible to write a normal Haskell program without extensions. It's not currently possible. The best effort in this direction is the GHC20xx process that Joachim has been leading us through. Recent discussions (including this one) contain hints on how to lean even stronger on this process to improve stability guarantees. That being said, the GR{1,2,3} articulated by Simon PJ look quite reasonable to me. On Mon, 2 Oct 2023 at 08:25, Moritz Angermann <moritz.angermann@gmail.com> wrote:
Simon,
Over the weekend, I've given this considerable thought and decided to approach it from a slightly different angle. I concur that we shouldn't duplicate or replace any existing work. I'm especially appreciative of Adam pointing out the current spreadsheet. Such insights highlight the value of our discussions!
My plan right now is as follows:
1. *GHC Experimental Proposal*: I'll draft a proposal for --ghc=experimental. While it won't mark anything as experimental immediately, it sets the groundwork for distinguishing between experimental and stable features. This will also help us introduce experimental features with a clear flag from the outset. 2. *Extension Life Cycle Discussion*: I'll reconnect with Adam and others regarding the extension life cycle proposal. The core idea of having a clear life cycle for extensions seems to be well-received. The nuances and details are what sparked our initial conversation. 3. *Marking Features as Experimental*: I plan to propose marking JavaScriptFFI, Linear Types, and Dependent Haskell as experimental for the time being. We'll gauge the community's response and gather feedback from the original authors during the proposal process. 4. *Stability Policy Proposal*: Based on our collective input, I'll draft a proposal centered on the stability policy.
With (1) and (2), I believe we are in a good position to take the GHC Extensions sheet (and also add GHC Features), and start moving them through the life-cycle into experimental features?
Additionally, I'll be:
- Reviewing prior work on template-haskell. - Exploring ways to make more libraries re-installable.
Lastly, let's not lose sight of:
- The Stability Working Group. - The GHC API Stability initiative from the HF.
Best, Moritz
On Fri, 29 Sept 2023 at 17:53, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Thank you for bringing us this far. I'd be happy to step up to drive this
further.
Thank you Moritz, that would be very helpful. I see the steps (*not *in dependency order) including
- Develop stability ideas for Template Haskell. I think we have agreed that it's a tricky case: widely used, but hard to stabilise - Develop a preliminary classification of language extensions, in partnership with the folk (who include Adam) working on the extension life cycle proposal <https://github.com/ghc-proposals/ghc-proposals/pull/601>. The preliminary spreadsheet <https://docs.google.com/spreadsheets/d/1sRIcNKdflX2ogrx2EF3vKOn0vmv-UEOdladBqtYXdaw/edit#gid=0>is helpful -- thank you Adam. Let's not duplicate this work! - Ditto for "experimental features". - Turn the Google doc into a GHC Proposal.
I see all this as the GHC counterpart to the GHC base-library proposal <https://github.com/haskellfoundation/tech-proposals/blob/main/proposals/accepted/051-ghc-base-libraries.rst>: our general goal is to make a clear boundary between "stable" and "experimental", so that:
- users know when they are moving into experimental land - developers know when they risk breaking stable code
While the boundary is unclear, misunderstandings arise in both directions.
Simon
On Thu, 28 Sept 2023 at 13:39, Moritz Angermann < moritz.angermann@gmail.com> wrote:
Simon,
Thank you for bringing us this far. I'd be happy to step up to drive this further.
I will say that I do see the tension you see as well. And I do believe if we come to a conclusion on this stability policy that it will make GHC development more rigorous, which I think is a good thing for all of us, not just the consumers of the compiler. I think we need to stay mindful that we can still freely experiment on the --std=experimental (or however that flag ends up being named) side. I see this whole discussion as leading us towards the language research reactor side of GHC being primarily confined behind --std=experimental, and the stability seeking (commercial application?) on the other side.
I do not yet see how we can end up with the inability to change. We will just have a clearer process for _breaking_ changes. This does absolutely not mean we have to end up in a local optimum, or that we can not change. We can!
Unless someone speaks up who does _not_ want me to drive, this, I'm happy to start driving this discussion (including writing the proposals, starting next week).
Best, Moritz
On Thu, 28 Sept 2023 at 19:30, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Should we have a document (or better spreadsheet?) with a bullet point
for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
I think that would be a helpful way to "ground" the discussion a bit more. (The spreadsheet should also give a preliminary classification of extensions, at least into stable/experimental.)
I'm running out of capacity to drive this debate, useful though it is. Does anyone else feel able to drive some of the legwork?
So far this is all informal committee discussion. The next step would be a GHC Proposal inviting broader feedback from the community. I'm just hoping that by debugging it between ourselves we can side-step some unproductive discussions in that bigger context.
I believe we need to take into account that we can’t end up classifying
most of todays Haskell programs unstable
There is a tension here. If we say something is "stable" then we have to be super-careful about changing it. (That's the whole point.) And yet if the feature (like INCOHERENT) is a flaky "you are on your own" unsafePerformIO-like feature, I am axious about tying ourselves into an inability to change the behaviour of corner cases. I'm not sure how to resolve this tension.
Simon
On Thu, 28 Sept 2023 at 02:20, Moritz Angermann < moritz.angermann@gmail.com> wrote:
I think we are moving in the right direction! I do see however the tension rising on (2). And without being clear about (2), I don’t think we can properly agree on (1). We can agree on (1) in principle, but we need to clarify what we consider unstable/experimental, as a precondition to have finale agreement on (1). Otherwise people might agree to (1), only to be surprised by (2). For (3), I’d be happy to try to get my employer to provide resources for the implementation of —std=experimental.
Thusly I believe we should start to build a list of features we consider sufficiently experimental that they should preclude an existing Haskell program from being considered stable. This list for me contains so far:
- Linear Types - Dependent Haskell
Adam pointed out experimental backend and non-tire-1 platforms. I tend to agree with this, but see this distinctly separate from the language stability (outside of backend specific language extensions, e.g. JSFFI).
Platforms/backends may be experimental but those are (safe for specific lang exts) orthogonal to the Haskell code the compiler accepts.
Should we have a document (or better spreadsheet?) with a bullet point for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
Best, Moritz
On Wed, 27 Sep 2023 at 10:35 PM, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
it's essential that we continue to have these discussions to ensure > we're making the best decisions for the project and our community. >
Yes exactly! Its tricky and nuanced; hence trying to articulate something in a concrete doc, so we are all on the same page (literally!).
However, deprecation cycles don't mean we're averse to major changes. > It means we introduce them responsibly. When we believe a superior design > is possible, we can start a deprecation process to transition towards it. >
I have tried to make this explicit in Section 4. See what you think.
I think there are three phases
1. Agree this document. Is it what we want. 2. Categorise extensions into stable/experimental, and identify experimental language features. 3. Implement --std=experimental (Section 6).
(1) is what we are doing now. (2) will be some work, done by us. (3) is a larger task: it will require significant work to implement, and may impose unwelcome churn of its own. But that should not stop us doing (1) and (2).
Simon
-
On Wed, 27 Sept 2023 at 10:20, Moritz Angermann < moritz.angermann@gmail.com> wrote:
> Dear Adam, > > Thank you for your thoughtful feedback. I understand your > reservations, and it's essential that we continue to have these discussions > to ensure we're making the best decisions for the project and our > community. Let me address each of your points in turn: > - Cognitive Overhead for Users: > I understand the concern about cognitive overhead due to the > inability to remove complexity. However, our primary intention is to ensure > a gradual transition for our users rather than abrupt shifts. Introducing > changes via deprecation cycles allows users to adjust to modifications over > time, reducing the immediate cognitive load. It's a balance between > stability and simplicity, and I believe this approach allows us still to > reduce complexity. > > - Maintenance Burden in the Compiler: > Maintaining backward compatibility does indeed introduce some > overhead. Still, it also encourages a more disciplined and considered > approach to changes. With our deprecation cycles in place, it's not that we > never remove complexity; rather, we do it in a way that provides ample time > for adjustments. This benefits both the development team and the community. > > - Risk of Local Optimum: > This is a valid concern. However, deprecation cycles don't mean > we're averse to major changes. It means we introduce them responsibly. When > we believe a superior design is possible, we can start a deprecation > process to transition towards it. The flexibility and duration of our > deprecation cycles can be tailored depending on the severity of the > breaking change. > > - Discouraging Volunteer Contributors: > I understand that lengthy approval processes can be off-putting. But > it's crucial to note that a rigorous process ensures the consistency and > reliability of our project. We always welcome and value contributions. > Moreover, I believe this stability policy will provide us with clear > guardrails on how changes can be contributed. > > I will not disagree on the costs. I do believe though that the costs > for _breaking_ changes in the compiler ought to be borne by the people > making the change, instead of those who use the compiler (and may not even > benefit of those changes that caused breakage). I also see the team > maintaining GHC as the one to enforce this; they are the ones who cut the > releases. The fact that we may have breaking changes due to _bugs_ is > covered explicitly in the stability policy document. > > With my CLC hat on, I have been focusing on the same stability > guidelines as well (if it breaks existing code, I have been against those > changes without deprecation policies). The issues with the > template-haskell, and ghc library are noted. For the ghc library the > question will remain if we intent to provide a stable api to the compiler > or not. I believe many tools would like to have one, and if we relegate > anything unstable to ghc-experimental this might be achieved. For > template-haskell this is a bigger concern. Maybe we can collectively come > up with a solution that would allow us to provide a more insulated template > haskell interface from the compiler. > > However for template-haskell we might also need to look at what > exactly caused those breaking changes in the past. > > What this document outlines (in my understanding) is that any > experimental feature development can _only_ be visible behind > --std=experimental, and the dependency of ghc-experimental. Unless those > are given, the compiler should accept existing programs. This should allow > us enough room to innovate (everyone is always free to opt-in to bleeding > edge features with --std=experimental). I also believe that most of what > we have today will need to be treated as non-experimental simply because we > did not have that mechanism before. We don't want to break existing > programs as much as possible, thus relegating existing features into > --std=experimental (except for some fairly clear ones: e.g. Dependent > Haskell, and Linear Types?) is not really possible. What we can however do > is start deprecation phases for a few versions, moving features we consider > highly experimental (or maybe even bad) into `--std=experimental`. Just by > having deprecation phases and given the ecosystem enough time to adjust > (and provide feedback) we might come to different conclusions. > > As I've also outlined in the document, _if_ GHC was trivially > swappable, companies like IOG would _love_ to try new compilers and report > back bugs and regressions. As it is today, we can't. Making a large live > codebase compatible with 9.8 is a multiple weeks effort. Experimenting with > nightlies is technically impossible. _If_ I could setup the built of our > software trivial with ghc nightlies, I'd be _happy_ to build the > infrastructure out it to provide performance regressions (compilation, > runtime, ...) for our codebase and provide the feedback to the GHC team; > however I can't. And thus I'm stuck patching and fixing 8.10, and 9.2 > today. 9.6 maybe soon, but likely at the point in time where 9.6 is not > going to see any further releases, so I can spare trying to even forward > port my patches to HEAD. Not that I could even test them with head > properly, as our source is not accepted by HEAD. Thus I end up writing > patches against old stale branches. This to me is a fairly big > discouragement from contributing to GHC. > > Best, > Moritz > > On Mon, 25 Sept 2023 at 15:17, Adam Gundry <adam@well-typed.com> > wrote: > >> I'm afraid that I'm somewhat sceptical of this approach. >> >> A strong stability guarantee is certainly a valuable goal, but it >> also >> comes with costs, which I'd like to see more clearly articulated. >> Some >> of them include: >> >> * Cognitive overhead for users, because of the inability to >> remove >> complexity from the design. >> >> * Increasing maintenance burden in the compiler, because of the >> additional work needed to implement new features and the inability >> to >> remove complexity from the implementation. >> >> * A risk of getting stuck in a local optimum, because moving to a >> better design would entail breaking changes. >> >> * Discouraging volunteer contributors, who are much less likely >> to >> work on a potentially beneficial change if the process for getting >> it >> approved is too onerous. (I'm worried we're already reaching that >> point >> due to the increasing burden of well-intentioned processes.) >> >> Ultimately every proposed change has a cost-benefit trade-off, with >> risk >> of breakage being one of the costs. We need to consciously evaluate >> that >> trade-off on a case-by-case basis. Almost all changes might break >> something (e.g. by regressing performance, or for Hyrum's Law >> reasons), >> so there needs to be a proportionate assessment of how likely each >> change is to be damaging in practice, bearing in mind that such an >> assessment is itself costly and limited in scope. >> >> It seems to me that the GHC team have taken on board lessons >> regarding >> stability of the language, and the extension system already gives >> quite >> a lot of flexibility to evolve the language in a >> backwards-compatible >> way. In my experience, the key stability problems preventing >> upgrades to >> recent GHC releases are: >> >> * The cascading effect of breaking changes in one library causing >> the >> need to upgrade libraries which depend upon it. This is primarily >> under >> the control of the CLC and library maintainers, however, not the >> GHC >> team. It would help if base was minimal and reinstallable, but that >> isn't a total solution either, because you'd still have to worry >> about >> packages depending on template-haskell or the ghc package itself. >> >> * Performance regressions or critical bugs. These tend to be a >> significant obstacle to upgrading for smaller commercial users. But >> spending more of our limited resources on stability of the language >> means fewer resources for resolving these issues. >> >> There's surely more we can do here, but let's be careful not to pay >> too >> many costs to achieve stability of the *language* alone, when >> stability >> of the *libraries* and *implementation* are both more important and >> harder to fix. >> >> Adam >> >> >> On 22/09/2023 10:53, Simon Peyton Jones wrote: >> > Dear GHC SC >> > >> > To avoid derailing the debate about -Wsevere >> > < >> https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, >> and HasField redesign < >> https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, >> I'm starting a new (email for now) thread about stability. >> > >> > I have tried to articulate what I believe is an evolving >> consensus in >> > this document >> > < >> https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47Zulga... >> >. >> > >> > If we converge, we'll turn that into a proper PR for the GHC >> proposal >> > process, although it has wider implications than just GHC >> proposals and >> > we should share with a broader audience. But let's start with >> the >> > steering committee. >> > >> > Any views? You all have edit rights. >> > >> > I think that the draft covers Moritz's and Julian's goals, at >> least that >> > was my intention. I have pasted Moritz's last email below, for >> context. >> > >> > Simon >> > >> > >> > ========= Moritz's last email ============ >> > >> > Now, this is derailing the original discussion a bit, and I'm not >> sure >> > how far we want to take this. But, regarding @Simon Marlow >> > <mailto:marlowsd@gmail.com>'s comment >> > >> > This is one cultural aspect of our community I'd like to >> shift: the >> > expectation that it's OK to make breaking changes as long as >> you >> > warn about >> > them or go through a migration cycle. It just isn't! (and I >> speak as >> > someone who used to make lots of changes, I'm now fully >> repentant!). >> > That's >> > not to say that we shouldn't ever change anything, but when >> > considering the >> > cost/benefit tradeoff adding a migration cycle doesn't reduce >> the >> > cost, it >> > just defers it. >> > >> > >> > I actually read this as we should stop having breaking changes to >> begin >> > with. And _if_ we >> > do have breaking changes, that deprecation does not change the >> need to >> > actually change >> > code (cost). As outlined in my reply to that, and @Richard >> Eisenberg >> > <mailto:lists@richarde.dev>'s observation, it >> > "smears" the cost. The--to me--_much_ bigger implication of >> deprecation >> > cycles is that we >> > _inform_ our _customers_ about upcoming changes _early_, instead >> of >> > _after the fact_. We >> > also give them ample time to react. Being by changing their code, >> or >> > raising their concerns. >> > Would the Simplified Subsumptions / Deep Subsumptions change >> have looked >> > differently? >> > As such I see deprecation cycles as orthogonal to the question if >> we >> > should have breaking >> > changes to begin with. >> > >> > Thus I believe the following: >> > >> > - Do have a deprecation cycle if possible. >> > - Do not treat a deprecation cycle as an excuse. Costs are >> deferred >> > but are as large as ever. >> > >> > >> > should be upgraded to: >> > - Preferably _no_ breaking changes. >> > - If breaking changes, then with a deprecation cycle, unless >> technically >> > infeasible. >> > - An understanding that any breaking change incurs significant >> costs. >> > >> > Ocaml recently added multicore support, and they put tremendous >> effort >> > into making >> > sure it keeps backwards compatibility: >> > >> https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md >> > < >> https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md >> > >> > >> > PS: we should also agree that a "stable" extension should not >> > require dependencies on ghc-experimental. To become stable, >> any >> > library support for an extension must move into `base`. >> > >> > >> > This seems like a good idea, however I still remain that >> _experimental_ >> > features should not be on-by-default in a stable compiler. Yes, >> ideally >> > I'd not even see them in a stable compiler, but I know this view >> is >> > contentious. The use of `ghc-experimental` should therefore be >> guarded >> > by `--std=experimental` as Julian suggested. That is a loud >> opt-in to >> > experimental features. >> > >> >> -- >> Adam Gundry, Haskell Consultant >> Well-Typed LLP, https://www.well-typed.com/ >> >> Registered in England & Wales, OC335890 >> 27 Old Gloucester Street, London WC1N 3AX, England >> <https://www.google.com/maps/search/27+Old+Gloucester+Street,+London+WC1N+3AX,+England?entry=gmail&source=g> >> >> _______________________________________________ >> ghc-steering-committee mailing list >> ghc-steering-committee@haskell.org >> >> https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee >> > _______________________________________________ > ghc-steering-committee mailing list > ghc-steering-committee@haskell.org > > https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee > _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
-- Arnaud Spiwack Director, Research at https://moduscreate.com and https://tweag.io.
Moritz That sounds good to me. Just one thought: - I really do think it is helpful to separate our *General Rules *(GR1-3) from a machine supported *enforcement mechanism *(Section 6). The latter is slower and more complicated than the former, and I'd hate to see us stall on articulating our principles because we don't yet have a full enforcement mechanism. I understand the desirability of enforcement, so you can say "in my software stack, all packages are stable, and that is checked every night. So I'm fine with you sketching a proposal for how to do it. I would just not like to de-rail the GR1-3 debate, including the classification we develop with the extension-life-cycle-proposal folk. Thanks for leading on this. I think we are all signed up to a constructive dialogue that values the balance between innovation and stability, and I'm optimistic that we can manage that balance better than we do today, *without *just saying "innovation wins" or "stability wins". Speaking personally, I'm very keen on innovation ("GHC as a laboratory"), as you know, but I truly respect the need for stability which is why I have invested so much time in the base-library discussion and now this one. Onward! Simon On Mon, 2 Oct 2023 at 07:25, Moritz Angermann <moritz.angermann@gmail.com> wrote:
Simon,
Over the weekend, I've given this considerable thought and decided to approach it from a slightly different angle. I concur that we shouldn't duplicate or replace any existing work. I'm especially appreciative of Adam pointing out the current spreadsheet. Such insights highlight the value of our discussions!
My plan right now is as follows:
1. *GHC Experimental Proposal*: I'll draft a proposal for --ghc=experimental. While it won't mark anything as experimental immediately, it sets the groundwork for distinguishing between experimental and stable features. This will also help us introduce experimental features with a clear flag from the outset. 2. *Extension Life Cycle Discussion*: I'll reconnect with Adam and others regarding the extension life cycle proposal. The core idea of having a clear life cycle for extensions seems to be well-received. The nuances and details are what sparked our initial conversation. 3. *Marking Features as Experimental*: I plan to propose marking JavaScriptFFI, Linear Types, and Dependent Haskell as experimental for the time being. We'll gauge the community's response and gather feedback from the original authors during the proposal process. 4. *Stability Policy Proposal*: Based on our collective input, I'll draft a proposal centered on the stability policy.
With (1) and (2), I believe we are in a good position to take the GHC Extensions sheet (and also add GHC Features), and start moving them through the life-cycle into experimental features?
Additionally, I'll be:
- Reviewing prior work on template-haskell. - Exploring ways to make more libraries re-installable.
Lastly, let's not lose sight of:
- The Stability Working Group. - The GHC API Stability initiative from the HF.
Best, Moritz
On Fri, 29 Sept 2023 at 17:53, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Thank you for bringing us this far. I'd be happy to step up to drive this
further.
Thank you Moritz, that would be very helpful. I see the steps (*not *in dependency order) including
- Develop stability ideas for Template Haskell. I think we have agreed that it's a tricky case: widely used, but hard to stabilise - Develop a preliminary classification of language extensions, in partnership with the folk (who include Adam) working on the extension life cycle proposal <https://github.com/ghc-proposals/ghc-proposals/pull/601>. The preliminary spreadsheet <https://docs.google.com/spreadsheets/d/1sRIcNKdflX2ogrx2EF3vKOn0vmv-UEOdladBqtYXdaw/edit#gid=0>is helpful -- thank you Adam. Let's not duplicate this work! - Ditto for "experimental features". - Turn the Google doc into a GHC Proposal.
I see all this as the GHC counterpart to the GHC base-library proposal <https://github.com/haskellfoundation/tech-proposals/blob/main/proposals/accepted/051-ghc-base-libraries.rst>: our general goal is to make a clear boundary between "stable" and "experimental", so that:
- users know when they are moving into experimental land - developers know when they risk breaking stable code
While the boundary is unclear, misunderstandings arise in both directions.
Simon
On Thu, 28 Sept 2023 at 13:39, Moritz Angermann < moritz.angermann@gmail.com> wrote:
Simon,
Thank you for bringing us this far. I'd be happy to step up to drive this further.
I will say that I do see the tension you see as well. And I do believe if we come to a conclusion on this stability policy that it will make GHC development more rigorous, which I think is a good thing for all of us, not just the consumers of the compiler. I think we need to stay mindful that we can still freely experiment on the --std=experimental (or however that flag ends up being named) side. I see this whole discussion as leading us towards the language research reactor side of GHC being primarily confined behind --std=experimental, and the stability seeking (commercial application?) on the other side.
I do not yet see how we can end up with the inability to change. We will just have a clearer process for _breaking_ changes. This does absolutely not mean we have to end up in a local optimum, or that we can not change. We can!
Unless someone speaks up who does _not_ want me to drive, this, I'm happy to start driving this discussion (including writing the proposals, starting next week).
Best, Moritz
On Thu, 28 Sept 2023 at 19:30, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Should we have a document (or better spreadsheet?) with a bullet point
for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
I think that would be a helpful way to "ground" the discussion a bit more. (The spreadsheet should also give a preliminary classification of extensions, at least into stable/experimental.)
I'm running out of capacity to drive this debate, useful though it is. Does anyone else feel able to drive some of the legwork?
So far this is all informal committee discussion. The next step would be a GHC Proposal inviting broader feedback from the community. I'm just hoping that by debugging it between ourselves we can side-step some unproductive discussions in that bigger context.
I believe we need to take into account that we can’t end up classifying
most of todays Haskell programs unstable
There is a tension here. If we say something is "stable" then we have to be super-careful about changing it. (That's the whole point.) And yet if the feature (like INCOHERENT) is a flaky "you are on your own" unsafePerformIO-like feature, I am axious about tying ourselves into an inability to change the behaviour of corner cases. I'm not sure how to resolve this tension.
Simon
On Thu, 28 Sept 2023 at 02:20, Moritz Angermann < moritz.angermann@gmail.com> wrote:
I think we are moving in the right direction! I do see however the tension rising on (2). And without being clear about (2), I don’t think we can properly agree on (1). We can agree on (1) in principle, but we need to clarify what we consider unstable/experimental, as a precondition to have finale agreement on (1). Otherwise people might agree to (1), only to be surprised by (2). For (3), I’d be happy to try to get my employer to provide resources for the implementation of —std=experimental.
Thusly I believe we should start to build a list of features we consider sufficiently experimental that they should preclude an existing Haskell program from being considered stable. This list for me contains so far:
- Linear Types - Dependent Haskell
Adam pointed out experimental backend and non-tire-1 platforms. I tend to agree with this, but see this distinctly separate from the language stability (outside of backend specific language extensions, e.g. JSFFI).
Platforms/backends may be experimental but those are (safe for specific lang exts) orthogonal to the Haskell code the compiler accepts.
Should we have a document (or better spreadsheet?) with a bullet point for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
Best, Moritz
On Wed, 27 Sep 2023 at 10:35 PM, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
it's essential that we continue to have these discussions to ensure > we're making the best decisions for the project and our community. >
Yes exactly! Its tricky and nuanced; hence trying to articulate something in a concrete doc, so we are all on the same page (literally!).
However, deprecation cycles don't mean we're averse to major changes. > It means we introduce them responsibly. When we believe a superior design > is possible, we can start a deprecation process to transition towards it. >
I have tried to make this explicit in Section 4. See what you think.
I think there are three phases
1. Agree this document. Is it what we want. 2. Categorise extensions into stable/experimental, and identify experimental language features. 3. Implement --std=experimental (Section 6).
(1) is what we are doing now. (2) will be some work, done by us. (3) is a larger task: it will require significant work to implement, and may impose unwelcome churn of its own. But that should not stop us doing (1) and (2).
Simon
-
On Wed, 27 Sept 2023 at 10:20, Moritz Angermann < moritz.angermann@gmail.com> wrote:
> Dear Adam, > > Thank you for your thoughtful feedback. I understand your > reservations, and it's essential that we continue to have these discussions > to ensure we're making the best decisions for the project and our > community. Let me address each of your points in turn: > - Cognitive Overhead for Users: > I understand the concern about cognitive overhead due to the > inability to remove complexity. However, our primary intention is to ensure > a gradual transition for our users rather than abrupt shifts. Introducing > changes via deprecation cycles allows users to adjust to modifications over > time, reducing the immediate cognitive load. It's a balance between > stability and simplicity, and I believe this approach allows us still to > reduce complexity. > > - Maintenance Burden in the Compiler: > Maintaining backward compatibility does indeed introduce some > overhead. Still, it also encourages a more disciplined and considered > approach to changes. With our deprecation cycles in place, it's not that we > never remove complexity; rather, we do it in a way that provides ample time > for adjustments. This benefits both the development team and the community. > > - Risk of Local Optimum: > This is a valid concern. However, deprecation cycles don't mean > we're averse to major changes. It means we introduce them responsibly. When > we believe a superior design is possible, we can start a deprecation > process to transition towards it. The flexibility and duration of our > deprecation cycles can be tailored depending on the severity of the > breaking change. > > - Discouraging Volunteer Contributors: > I understand that lengthy approval processes can be off-putting. But > it's crucial to note that a rigorous process ensures the consistency and > reliability of our project. We always welcome and value contributions. > Moreover, I believe this stability policy will provide us with clear > guardrails on how changes can be contributed. > > I will not disagree on the costs. I do believe though that the costs > for _breaking_ changes in the compiler ought to be borne by the people > making the change, instead of those who use the compiler (and may not even > benefit of those changes that caused breakage). I also see the team > maintaining GHC as the one to enforce this; they are the ones who cut the > releases. The fact that we may have breaking changes due to _bugs_ is > covered explicitly in the stability policy document. > > With my CLC hat on, I have been focusing on the same stability > guidelines as well (if it breaks existing code, I have been against those > changes without deprecation policies). The issues with the > template-haskell, and ghc library are noted. For the ghc library the > question will remain if we intent to provide a stable api to the compiler > or not. I believe many tools would like to have one, and if we relegate > anything unstable to ghc-experimental this might be achieved. For > template-haskell this is a bigger concern. Maybe we can collectively come > up with a solution that would allow us to provide a more insulated template > haskell interface from the compiler. > > However for template-haskell we might also need to look at what > exactly caused those breaking changes in the past. > > What this document outlines (in my understanding) is that any > experimental feature development can _only_ be visible behind > --std=experimental, and the dependency of ghc-experimental. Unless those > are given, the compiler should accept existing programs. This should allow > us enough room to innovate (everyone is always free to opt-in to bleeding > edge features with --std=experimental). I also believe that most of what > we have today will need to be treated as non-experimental simply because we > did not have that mechanism before. We don't want to break existing > programs as much as possible, thus relegating existing features into > --std=experimental (except for some fairly clear ones: e.g. Dependent > Haskell, and Linear Types?) is not really possible. What we can however do > is start deprecation phases for a few versions, moving features we consider > highly experimental (or maybe even bad) into `--std=experimental`. Just by > having deprecation phases and given the ecosystem enough time to adjust > (and provide feedback) we might come to different conclusions. > > As I've also outlined in the document, _if_ GHC was trivially > swappable, companies like IOG would _love_ to try new compilers and report > back bugs and regressions. As it is today, we can't. Making a large live > codebase compatible with 9.8 is a multiple weeks effort. Experimenting with > nightlies is technically impossible. _If_ I could setup the built of our > software trivial with ghc nightlies, I'd be _happy_ to build the > infrastructure out it to provide performance regressions (compilation, > runtime, ...) for our codebase and provide the feedback to the GHC team; > however I can't. And thus I'm stuck patching and fixing 8.10, and 9.2 > today. 9.6 maybe soon, but likely at the point in time where 9.6 is not > going to see any further releases, so I can spare trying to even forward > port my patches to HEAD. Not that I could even test them with head > properly, as our source is not accepted by HEAD. Thus I end up writing > patches against old stale branches. This to me is a fairly big > discouragement from contributing to GHC. > > Best, > Moritz > > On Mon, 25 Sept 2023 at 15:17, Adam Gundry <adam@well-typed.com> > wrote: > >> I'm afraid that I'm somewhat sceptical of this approach. >> >> A strong stability guarantee is certainly a valuable goal, but it >> also >> comes with costs, which I'd like to see more clearly articulated. >> Some >> of them include: >> >> * Cognitive overhead for users, because of the inability to >> remove >> complexity from the design. >> >> * Increasing maintenance burden in the compiler, because of the >> additional work needed to implement new features and the inability >> to >> remove complexity from the implementation. >> >> * A risk of getting stuck in a local optimum, because moving to a >> better design would entail breaking changes. >> >> * Discouraging volunteer contributors, who are much less likely >> to >> work on a potentially beneficial change if the process for getting >> it >> approved is too onerous. (I'm worried we're already reaching that >> point >> due to the increasing burden of well-intentioned processes.) >> >> Ultimately every proposed change has a cost-benefit trade-off, with >> risk >> of breakage being one of the costs. We need to consciously evaluate >> that >> trade-off on a case-by-case basis. Almost all changes might break >> something (e.g. by regressing performance, or for Hyrum's Law >> reasons), >> so there needs to be a proportionate assessment of how likely each >> change is to be damaging in practice, bearing in mind that such an >> assessment is itself costly and limited in scope. >> >> It seems to me that the GHC team have taken on board lessons >> regarding >> stability of the language, and the extension system already gives >> quite >> a lot of flexibility to evolve the language in a >> backwards-compatible >> way. In my experience, the key stability problems preventing >> upgrades to >> recent GHC releases are: >> >> * The cascading effect of breaking changes in one library causing >> the >> need to upgrade libraries which depend upon it. This is primarily >> under >> the control of the CLC and library maintainers, however, not the >> GHC >> team. It would help if base was minimal and reinstallable, but that >> isn't a total solution either, because you'd still have to worry >> about >> packages depending on template-haskell or the ghc package itself. >> >> * Performance regressions or critical bugs. These tend to be a >> significant obstacle to upgrading for smaller commercial users. But >> spending more of our limited resources on stability of the language >> means fewer resources for resolving these issues. >> >> There's surely more we can do here, but let's be careful not to pay >> too >> many costs to achieve stability of the *language* alone, when >> stability >> of the *libraries* and *implementation* are both more important and >> harder to fix. >> >> Adam >> >> >> On 22/09/2023 10:53, Simon Peyton Jones wrote: >> > Dear GHC SC >> > >> > To avoid derailing the debate about -Wsevere >> > < >> https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, >> and HasField redesign < >> https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, >> I'm starting a new (email for now) thread about stability. >> > >> > I have tried to articulate what I believe is an evolving >> consensus in >> > this document >> > < >> https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47Zulga... >> >. >> > >> > If we converge, we'll turn that into a proper PR for the GHC >> proposal >> > process, although it has wider implications than just GHC >> proposals and >> > we should share with a broader audience. But let's start with >> the >> > steering committee. >> > >> > Any views? You all have edit rights. >> > >> > I think that the draft covers Moritz's and Julian's goals, at >> least that >> > was my intention. I have pasted Moritz's last email below, for >> context. >> > >> > Simon >> > >> > >> > ========= Moritz's last email ============ >> > >> > Now, this is derailing the original discussion a bit, and I'm not >> sure >> > how far we want to take this. But, regarding @Simon Marlow >> > <mailto:marlowsd@gmail.com>'s comment >> > >> > This is one cultural aspect of our community I'd like to >> shift: the >> > expectation that it's OK to make breaking changes as long as >> you >> > warn about >> > them or go through a migration cycle. It just isn't! (and I >> speak as >> > someone who used to make lots of changes, I'm now fully >> repentant!). >> > That's >> > not to say that we shouldn't ever change anything, but when >> > considering the >> > cost/benefit tradeoff adding a migration cycle doesn't reduce >> the >> > cost, it >> > just defers it. >> > >> > >> > I actually read this as we should stop having breaking changes to >> begin >> > with. And _if_ we >> > do have breaking changes, that deprecation does not change the >> need to >> > actually change >> > code (cost). As outlined in my reply to that, and @Richard >> Eisenberg >> > <mailto:lists@richarde.dev>'s observation, it >> > "smears" the cost. The--to me--_much_ bigger implication of >> deprecation >> > cycles is that we >> > _inform_ our _customers_ about upcoming changes _early_, instead >> of >> > _after the fact_. We >> > also give them ample time to react. Being by changing their code, >> or >> > raising their concerns. >> > Would the Simplified Subsumptions / Deep Subsumptions change >> have looked >> > differently? >> > As such I see deprecation cycles as orthogonal to the question if >> we >> > should have breaking >> > changes to begin with. >> > >> > Thus I believe the following: >> > >> > - Do have a deprecation cycle if possible. >> > - Do not treat a deprecation cycle as an excuse. Costs are >> deferred >> > but are as large as ever. >> > >> > >> > should be upgraded to: >> > - Preferably _no_ breaking changes. >> > - If breaking changes, then with a deprecation cycle, unless >> technically >> > infeasible. >> > - An understanding that any breaking change incurs significant >> costs. >> > >> > Ocaml recently added multicore support, and they put tremendous >> effort >> > into making >> > sure it keeps backwards compatibility: >> > >> https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md >> > < >> https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md >> > >> > >> > PS: we should also agree that a "stable" extension should not >> > require dependencies on ghc-experimental. To become stable, >> any >> > library support for an extension must move into `base`. >> > >> > >> > This seems like a good idea, however I still remain that >> _experimental_ >> > features should not be on-by-default in a stable compiler. Yes, >> ideally >> > I'd not even see them in a stable compiler, but I know this view >> is >> > contentious. The use of `ghc-experimental` should therefore be >> guarded >> > by `--std=experimental` as Julian suggested. That is a loud >> opt-in to >> > experimental features. >> > >> >> -- >> Adam Gundry, Haskell Consultant >> Well-Typed LLP, https://www.well-typed.com/ >> >> Registered in England & Wales, OC335890 >> 27 Old Gloucester Street, London WC1N 3AX, England >> <https://www.google.com/maps/search/27+Old+Gloucester+Street,+London+WC1N+3AX,+England?entry=gmail&source=g> >> >> _______________________________________________ >> ghc-steering-committee mailing list >> ghc-steering-committee@haskell.org >> >> https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee >> > _______________________________________________ > ghc-steering-committee mailing list > ghc-steering-committee@haskell.org > > https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee >
Dear all, I've been chatting about this with colleagues, and I've come to understand better why I feel rather dismayed at the turn the conversation is taking. To be blunt, we seem to be developing a cure without having a diagnosis. The mandate here is “make Haskell more stable” which is quite commendable, but it's also very imprecise. I'd like us to have some concrete headline issues to fix. How has the backward compatibility of Haskell been compromised in the past, say, 2 years? In particular, how have our current policies failed (then we'd need to fix them somehow), or where are our policies blind? Moritz: you said you were currently experiencing this at work (in fact, as you probably know, I got some information on this indirectly), could you share with us, say, the 3 most painful aspects of the migration you're undertaking? So that they can be analysed? Avoid those related to base changing because there's little that this committee can do about it (though see follow-up email). On Tue, 3 Oct 2023 at 12:08, Simon Peyton Jones <simon.peytonjones@gmail.com> wrote:
Moritz
That sounds good to me. Just one thought:
- I really do think it is helpful to separate our *General Rules *(GR1-3) from a machine supported *enforcement mechanism *(Section 6). The latter is slower and more complicated than the former, and I'd hate to see us stall on articulating our principles because we don't yet have a full enforcement mechanism.
I understand the desirability of enforcement, so you can say "in my software stack, all packages are stable, and that is checked every night. So I'm fine with you sketching a proposal for how to do it. I would just not like to de-rail the GR1-3 debate, including the classification we develop with the extension-life-cycle-proposal folk.
Thanks for leading on this. I think we are all signed up to a constructive dialogue that values the balance between innovation and stability, and I'm optimistic that we can manage that balance better than we do today, *without *just saying "innovation wins" or "stability wins". Speaking personally, I'm very keen on innovation ("GHC as a laboratory"), as you know, but I truly respect the need for stability which is why I have invested so much time in the base-library discussion and now this one. Onward!
Simon
On Mon, 2 Oct 2023 at 07:25, Moritz Angermann <moritz.angermann@gmail.com> wrote:
Simon,
Over the weekend, I've given this considerable thought and decided to approach it from a slightly different angle. I concur that we shouldn't duplicate or replace any existing work. I'm especially appreciative of Adam pointing out the current spreadsheet. Such insights highlight the value of our discussions!
My plan right now is as follows:
1. *GHC Experimental Proposal*: I'll draft a proposal for --ghc=experimental. While it won't mark anything as experimental immediately, it sets the groundwork for distinguishing between experimental and stable features. This will also help us introduce experimental features with a clear flag from the outset. 2. *Extension Life Cycle Discussion*: I'll reconnect with Adam and others regarding the extension life cycle proposal. The core idea of having a clear life cycle for extensions seems to be well-received. The nuances and details are what sparked our initial conversation. 3. *Marking Features as Experimental*: I plan to propose marking JavaScriptFFI, Linear Types, and Dependent Haskell as experimental for the time being. We'll gauge the community's response and gather feedback from the original authors during the proposal process. 4. *Stability Policy Proposal*: Based on our collective input, I'll draft a proposal centered on the stability policy.
With (1) and (2), I believe we are in a good position to take the GHC Extensions sheet (and also add GHC Features), and start moving them through the life-cycle into experimental features?
Additionally, I'll be:
- Reviewing prior work on template-haskell. - Exploring ways to make more libraries re-installable.
Lastly, let's not lose sight of:
- The Stability Working Group. - The GHC API Stability initiative from the HF.
Best, Moritz
On Fri, 29 Sept 2023 at 17:53, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Thank you for bringing us this far. I'd be happy to step up to drive
this further.
Thank you Moritz, that would be very helpful. I see the steps (*not *in dependency order) including
- Develop stability ideas for Template Haskell. I think we have agreed that it's a tricky case: widely used, but hard to stabilise - Develop a preliminary classification of language extensions, in partnership with the folk (who include Adam) working on the extension life cycle proposal <https://github.com/ghc-proposals/ghc-proposals/pull/601>. The preliminary spreadsheet <https://docs.google.com/spreadsheets/d/1sRIcNKdflX2ogrx2EF3vKOn0vmv-UEOdladBqtYXdaw/edit#gid=0>is helpful -- thank you Adam. Let's not duplicate this work! - Ditto for "experimental features". - Turn the Google doc into a GHC Proposal.
I see all this as the GHC counterpart to the GHC base-library proposal <https://github.com/haskellfoundation/tech-proposals/blob/main/proposals/accepted/051-ghc-base-libraries.rst>: our general goal is to make a clear boundary between "stable" and "experimental", so that:
- users know when they are moving into experimental land - developers know when they risk breaking stable code
While the boundary is unclear, misunderstandings arise in both directions.
Simon
On Thu, 28 Sept 2023 at 13:39, Moritz Angermann < moritz.angermann@gmail.com> wrote:
Simon,
Thank you for bringing us this far. I'd be happy to step up to drive this further.
I will say that I do see the tension you see as well. And I do believe if we come to a conclusion on this stability policy that it will make GHC development more rigorous, which I think is a good thing for all of us, not just the consumers of the compiler. I think we need to stay mindful that we can still freely experiment on the --std=experimental (or however that flag ends up being named) side. I see this whole discussion as leading us towards the language research reactor side of GHC being primarily confined behind --std=experimental, and the stability seeking (commercial application?) on the other side.
I do not yet see how we can end up with the inability to change. We will just have a clearer process for _breaking_ changes. This does absolutely not mean we have to end up in a local optimum, or that we can not change. We can!
Unless someone speaks up who does _not_ want me to drive, this, I'm happy to start driving this discussion (including writing the proposals, starting next week).
Best, Moritz
On Thu, 28 Sept 2023 at 19:30, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Should we have a document (or better spreadsheet?) with a bullet point
for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
I think that would be a helpful way to "ground" the discussion a bit more. (The spreadsheet should also give a preliminary classification of extensions, at least into stable/experimental.)
I'm running out of capacity to drive this debate, useful though it is. Does anyone else feel able to drive some of the legwork?
So far this is all informal committee discussion. The next step would be a GHC Proposal inviting broader feedback from the community. I'm just hoping that by debugging it between ourselves we can side-step some unproductive discussions in that bigger context.
I believe we need to take into account that we can’t end up
classifying most of todays Haskell programs unstable
There is a tension here. If we say something is "stable" then we have to be super-careful about changing it. (That's the whole point.) And yet if the feature (like INCOHERENT) is a flaky "you are on your own" unsafePerformIO-like feature, I am axious about tying ourselves into an inability to change the behaviour of corner cases. I'm not sure how to resolve this tension.
Simon
On Thu, 28 Sept 2023 at 02:20, Moritz Angermann < moritz.angermann@gmail.com> wrote:
I think we are moving in the right direction! I do see however the tension rising on (2). And without being clear about (2), I don’t think we can properly agree on (1). We can agree on (1) in principle, but we need to clarify what we consider unstable/experimental, as a precondition to have finale agreement on (1). Otherwise people might agree to (1), only to be surprised by (2). For (3), I’d be happy to try to get my employer to provide resources for the implementation of —std=experimental.
Thusly I believe we should start to build a list of features we consider sufficiently experimental that they should preclude an existing Haskell program from being considered stable. This list for me contains so far:
- Linear Types - Dependent Haskell
Adam pointed out experimental backend and non-tire-1 platforms. I tend to agree with this, but see this distinctly separate from the language stability (outside of backend specific language extensions, e.g. JSFFI).
Platforms/backends may be experimental but those are (safe for specific lang exts) orthogonal to the Haskell code the compiler accepts.
Should we have a document (or better spreadsheet?) with a bullet point for each experimental feature to be considered? I believe we need to take into account that we can’t end up classifying most of todays Haskell programs unstable. As such I’d like to propose that we’d add to each features a counter for how much of hackage (as a proxy for real world usage) uses the specific feature.
Best, Moritz
On Wed, 27 Sep 2023 at 10:35 PM, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
> it's essential that we continue to have these discussions to ensure >> we're making the best decisions for the project and our community. >> > > Yes exactly! Its tricky and nuanced; hence trying to articulate > something in a concrete doc, so we are all on the same page (literally!). > > However, deprecation cycles don't mean we're averse to major >> changes. It means we introduce them responsibly. When we believe a superior >> design is possible, we can start a deprecation process to transition >> towards it. >> > > I have tried to make this explicit in Section 4. See what you > think. > > I think there are three phases > > 1. Agree this document. Is it what we want. > 2. Categorise extensions into stable/experimental, and identify > experimental language features. > 3. Implement --std=experimental (Section 6). > > (1) is what we are doing now. (2) will be some work, done by us. > (3) is a larger task: it will require significant work to implement, and > may impose unwelcome churn of its own. But that should not stop us doing > (1) and (2). > > Simon > > - > > > On Wed, 27 Sept 2023 at 10:20, Moritz Angermann < > moritz.angermann@gmail.com> wrote: > >> Dear Adam, >> >> Thank you for your thoughtful feedback. I understand your >> reservations, and it's essential that we continue to have these discussions >> to ensure we're making the best decisions for the project and our >> community. Let me address each of your points in turn: >> - Cognitive Overhead for Users: >> I understand the concern about cognitive overhead due to the >> inability to remove complexity. However, our primary intention is to ensure >> a gradual transition for our users rather than abrupt shifts. Introducing >> changes via deprecation cycles allows users to adjust to modifications over >> time, reducing the immediate cognitive load. It's a balance between >> stability and simplicity, and I believe this approach allows us still to >> reduce complexity. >> >> - Maintenance Burden in the Compiler: >> Maintaining backward compatibility does indeed introduce some >> overhead. Still, it also encourages a more disciplined and considered >> approach to changes. With our deprecation cycles in place, it's not that we >> never remove complexity; rather, we do it in a way that provides ample time >> for adjustments. This benefits both the development team and the community. >> >> - Risk of Local Optimum: >> This is a valid concern. However, deprecation cycles don't mean >> we're averse to major changes. It means we introduce them responsibly. When >> we believe a superior design is possible, we can start a deprecation >> process to transition towards it. The flexibility and duration of our >> deprecation cycles can be tailored depending on the severity of the >> breaking change. >> >> - Discouraging Volunteer Contributors: >> I understand that lengthy approval processes can be off-putting. >> But it's crucial to note that a rigorous process ensures the consistency >> and reliability of our project. We always welcome and value contributions. >> Moreover, I believe this stability policy will provide us with clear >> guardrails on how changes can be contributed. >> >> I will not disagree on the costs. I do believe though that the >> costs for _breaking_ changes in the compiler ought to be borne by the >> people making the change, instead of those who use the compiler (and may >> not even benefit of those changes that caused breakage). I also see the >> team maintaining GHC as the one to enforce this; they are the ones who cut >> the releases. The fact that we may have breaking changes due to _bugs_ is >> covered explicitly in the stability policy document. >> >> With my CLC hat on, I have been focusing on the same stability >> guidelines as well (if it breaks existing code, I have been against those >> changes without deprecation policies). The issues with the >> template-haskell, and ghc library are noted. For the ghc library the >> question will remain if we intent to provide a stable api to the compiler >> or not. I believe many tools would like to have one, and if we relegate >> anything unstable to ghc-experimental this might be achieved. For >> template-haskell this is a bigger concern. Maybe we can collectively come >> up with a solution that would allow us to provide a more insulated template >> haskell interface from the compiler. >> >> However for template-haskell we might also need to look at what >> exactly caused those breaking changes in the past. >> >> What this document outlines (in my understanding) is that any >> experimental feature development can _only_ be visible behind >> --std=experimental, and the dependency of ghc-experimental. Unless those >> are given, the compiler should accept existing programs. This should allow >> us enough room to innovate (everyone is always free to opt-in to bleeding >> edge features with --std=experimental). I also believe that most of what >> we have today will need to be treated as non-experimental simply because we >> did not have that mechanism before. We don't want to break existing >> programs as much as possible, thus relegating existing features into >> --std=experimental (except for some fairly clear ones: e.g. Dependent >> Haskell, and Linear Types?) is not really possible. What we can however do >> is start deprecation phases for a few versions, moving features we consider >> highly experimental (or maybe even bad) into `--std=experimental`. Just by >> having deprecation phases and given the ecosystem enough time to adjust >> (and provide feedback) we might come to different conclusions. >> >> As I've also outlined in the document, _if_ GHC was trivially >> swappable, companies like IOG would _love_ to try new compilers and report >> back bugs and regressions. As it is today, we can't. Making a large live >> codebase compatible with 9.8 is a multiple weeks effort. Experimenting with >> nightlies is technically impossible. _If_ I could setup the built of our >> software trivial with ghc nightlies, I'd be _happy_ to build the >> infrastructure out it to provide performance regressions (compilation, >> runtime, ...) for our codebase and provide the feedback to the GHC team; >> however I can't. And thus I'm stuck patching and fixing 8.10, and 9.2 >> today. 9.6 maybe soon, but likely at the point in time where 9.6 is not >> going to see any further releases, so I can spare trying to even forward >> port my patches to HEAD. Not that I could even test them with head >> properly, as our source is not accepted by HEAD. Thus I end up writing >> patches against old stale branches. This to me is a fairly big >> discouragement from contributing to GHC. >> >> Best, >> Moritz >> >> On Mon, 25 Sept 2023 at 15:17, Adam Gundry <adam@well-typed.com> >> wrote: >> >>> I'm afraid that I'm somewhat sceptical of this approach. >>> >>> A strong stability guarantee is certainly a valuable goal, but it >>> also >>> comes with costs, which I'd like to see more clearly articulated. >>> Some >>> of them include: >>> >>> * Cognitive overhead for users, because of the inability to >>> remove >>> complexity from the design. >>> >>> * Increasing maintenance burden in the compiler, because of the >>> additional work needed to implement new features and the inability >>> to >>> remove complexity from the implementation. >>> >>> * A risk of getting stuck in a local optimum, because moving to >>> a >>> better design would entail breaking changes. >>> >>> * Discouraging volunteer contributors, who are much less likely >>> to >>> work on a potentially beneficial change if the process for getting >>> it >>> approved is too onerous. (I'm worried we're already reaching that >>> point >>> due to the increasing burden of well-intentioned processes.) >>> >>> Ultimately every proposed change has a cost-benefit trade-off, >>> with risk >>> of breakage being one of the costs. We need to consciously >>> evaluate that >>> trade-off on a case-by-case basis. Almost all changes might break >>> something (e.g. by regressing performance, or for Hyrum's Law >>> reasons), >>> so there needs to be a proportionate assessment of how likely each >>> change is to be damaging in practice, bearing in mind that such an >>> assessment is itself costly and limited in scope. >>> >>> It seems to me that the GHC team have taken on board lessons >>> regarding >>> stability of the language, and the extension system already gives >>> quite >>> a lot of flexibility to evolve the language in a >>> backwards-compatible >>> way. In my experience, the key stability problems preventing >>> upgrades to >>> recent GHC releases are: >>> >>> * The cascading effect of breaking changes in one library >>> causing the >>> need to upgrade libraries which depend upon it. This is primarily >>> under >>> the control of the CLC and library maintainers, however, not the >>> GHC >>> team. It would help if base was minimal and reinstallable, but >>> that >>> isn't a total solution either, because you'd still have to worry >>> about >>> packages depending on template-haskell or the ghc package itself. >>> >>> * Performance regressions or critical bugs. These tend to be a >>> significant obstacle to upgrading for smaller commercial users. >>> But >>> spending more of our limited resources on stability of the >>> language >>> means fewer resources for resolving these issues. >>> >>> There's surely more we can do here, but let's be careful not to >>> pay too >>> many costs to achieve stability of the *language* alone, when >>> stability >>> of the *libraries* and *implementation* are both more important >>> and >>> harder to fix. >>> >>> Adam >>> >>> >>> On 22/09/2023 10:53, Simon Peyton Jones wrote: >>> > Dear GHC SC >>> > >>> > To avoid derailing the debate about -Wsevere >>> > < >>> https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, >>> and HasField redesign < >>> https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, >>> I'm starting a new (email for now) thread about stability. >>> > >>> > I have tried to articulate what I believe is an evolving >>> consensus in >>> > this document >>> > < >>> https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47Zulga... >>> >. >>> > >>> > If we converge, we'll turn that into a proper PR for the GHC >>> proposal >>> > process, although it has wider implications than just GHC >>> proposals and >>> > we should share with a broader audience. But let's start with >>> the >>> > steering committee. >>> > >>> > Any views? You all have edit rights. >>> > >>> > I think that the draft covers Moritz's and Julian's goals, at >>> least that >>> > was my intention. I have pasted Moritz's last email below, for >>> context. >>> > >>> > Simon >>> > >>> > >>> > ========= Moritz's last email ============ >>> > >>> > Now, this is derailing the original discussion a bit, and I'm >>> not sure >>> > how far we want to take this. But, regarding @Simon Marlow >>> > <mailto:marlowsd@gmail.com>'s comment >>> > >>> > This is one cultural aspect of our community I'd like to >>> shift: the >>> > expectation that it's OK to make breaking changes as long as >>> you >>> > warn about >>> > them or go through a migration cycle. It just isn't! (and I >>> speak as >>> > someone who used to make lots of changes, I'm now fully >>> repentant!). >>> > That's >>> > not to say that we shouldn't ever change anything, but when >>> > considering the >>> > cost/benefit tradeoff adding a migration cycle doesn't >>> reduce the >>> > cost, it >>> > just defers it. >>> > >>> > >>> > I actually read this as we should stop having breaking changes >>> to begin >>> > with. And _if_ we >>> > do have breaking changes, that deprecation does not change the >>> need to >>> > actually change >>> > code (cost). As outlined in my reply to that, and @Richard >>> Eisenberg >>> > <mailto:lists@richarde.dev>'s observation, it >>> > "smears" the cost. The--to me--_much_ bigger implication of >>> deprecation >>> > cycles is that we >>> > _inform_ our _customers_ about upcoming changes _early_, instead >>> of >>> > _after the fact_. We >>> > also give them ample time to react. Being by changing their >>> code, or >>> > raising their concerns. >>> > Would the Simplified Subsumptions / Deep Subsumptions change >>> have looked >>> > differently? >>> > As such I see deprecation cycles as orthogonal to the question >>> if we >>> > should have breaking >>> > changes to begin with. >>> > >>> > Thus I believe the following: >>> > >>> > - Do have a deprecation cycle if possible. >>> > - Do not treat a deprecation cycle as an excuse. Costs are >>> deferred >>> > but are as large as ever. >>> > >>> > >>> > should be upgraded to: >>> > - Preferably _no_ breaking changes. >>> > - If breaking changes, then with a deprecation cycle, unless >>> technically >>> > infeasible. >>> > - An understanding that any breaking change incurs significant >>> costs. >>> > >>> > Ocaml recently added multicore support, and they put tremendous >>> effort >>> > into making >>> > sure it keeps backwards compatibility: >>> > >>> https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md >>> > < >>> https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md >>> > >>> > >>> > PS: we should also agree that a "stable" extension should not >>> > require dependencies on ghc-experimental. To become stable, >>> any >>> > library support for an extension must move into `base`. >>> > >>> > >>> > This seems like a good idea, however I still remain that >>> _experimental_ >>> > features should not be on-by-default in a stable compiler. Yes, >>> ideally >>> > I'd not even see them in a stable compiler, but I know this view >>> is >>> > contentious. The use of `ghc-experimental` should therefore be >>> guarded >>> > by `--std=experimental` as Julian suggested. That is a loud >>> opt-in to >>> > experimental features. >>> > >>> >>> -- >>> Adam Gundry, Haskell Consultant >>> Well-Typed LLP, https://www.well-typed.com/ >>> >>> Registered in England & Wales, OC335890 >>> 27 Old Gloucester Street, London WC1N 3AX, England >>> <https://www.google.com/maps/search/27+Old+Gloucester+Street,+London+WC1N+3AX,+England?entry=gmail&source=g> >>> >>> _______________________________________________ >>> ghc-steering-committee mailing list >>> ghc-steering-committee@haskell.org >>> >>> https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee >>> >> _______________________________________________ >> ghc-steering-committee mailing list >> ghc-steering-committee@haskell.org >> >> https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee >> > _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
-- Arnaud Spiwack Director, Research at https://moduscreate.com and https://tweag.io.
The mandate here is “make Haskell more stable” which is quite commendable, but it's also very imprecise
Is it imprecise? I think our goal is pretty simple:* a program that compiles and runs with GHC 9.8 should also compile and run with GHC 9.10.* That's it. I think you subscribe to this as a general goal? Clearly that is a problem today: many users report that they are using years-old GHCs because the cost of upgrading to the latest version is so high. The General Rules I suggested at the start of this thread do no more than articulate that goal, and give some general principles that we seek to follow. I think that does no more than make *explicit *our *implicit *way of working (we spend a lot of time on back-compat discussions). That is, nothing really new here, just making it more explicit. Can you be more specific about what you don't like? Simon On Fri, 13 Oct 2023 at 09:45, Arnaud Spiwack <arnaud.spiwack@tweag.io> wrote:
Dear all,
I've been chatting about this with colleagues, and I've come to understand better why I feel rather dismayed at the turn the conversation is taking. To be blunt, we seem to be developing a cure without having a diagnosis. The mandate here is “make Haskell more stable” which is quite commendable, but it's also very imprecise. I'd like us to have some concrete headline issues to fix. How has the backward compatibility of Haskell been compromised in the past, say, 2 years? In particular, how have our current policies failed (then we'd need to fix them somehow), or where are our policies blind?
Moritz: you said you were currently experiencing this at work (in fact, as you probably know, I got some information on this indirectly), could you share with us, say, the 3 most painful aspects of the migration you're undertaking? So that they can be analysed? Avoid those related to base changing because there's little that this committee can do about it (though see follow-up email).
On Tue, 3 Oct 2023 at 12:08, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Moritz
That sounds good to me. Just one thought:
- I really do think it is helpful to separate our *General Rules *(GR1-3) from a machine supported *enforcement mechanism *(Section 6). The latter is slower and more complicated than the former, and I'd hate to see us stall on articulating our principles because we don't yet have a full enforcement mechanism.
I understand the desirability of enforcement, so you can say "in my software stack, all packages are stable, and that is checked every night. So I'm fine with you sketching a proposal for how to do it. I would just not like to de-rail the GR1-3 debate, including the classification we develop with the extension-life-cycle-proposal folk.
Thanks for leading on this. I think we are all signed up to a constructive dialogue that values the balance between innovation and stability, and I'm optimistic that we can manage that balance better than we do today, *without *just saying "innovation wins" or "stability wins". Speaking personally, I'm very keen on innovation ("GHC as a laboratory"), as you know, but I truly respect the need for stability which is why I have invested so much time in the base-library discussion and now this one. Onward!
Simon
On Mon, 2 Oct 2023 at 07:25, Moritz Angermann <moritz.angermann@gmail.com> wrote:
Simon,
Over the weekend, I've given this considerable thought and decided to approach it from a slightly different angle. I concur that we shouldn't duplicate or replace any existing work. I'm especially appreciative of Adam pointing out the current spreadsheet. Such insights highlight the value of our discussions!
My plan right now is as follows:
1. *GHC Experimental Proposal*: I'll draft a proposal for --ghc=experimental. While it won't mark anything as experimental immediately, it sets the groundwork for distinguishing between experimental and stable features. This will also help us introduce experimental features with a clear flag from the outset. 2. *Extension Life Cycle Discussion*: I'll reconnect with Adam and others regarding the extension life cycle proposal. The core idea of having a clear life cycle for extensions seems to be well-received. The nuances and details are what sparked our initial conversation. 3. *Marking Features as Experimental*: I plan to propose marking JavaScriptFFI, Linear Types, and Dependent Haskell as experimental for the time being. We'll gauge the community's response and gather feedback from the original authors during the proposal process. 4. *Stability Policy Proposal*: Based on our collective input, I'll draft a proposal centered on the stability policy.
With (1) and (2), I believe we are in a good position to take the GHC Extensions sheet (and also add GHC Features), and start moving them through the life-cycle into experimental features?
Additionally, I'll be:
- Reviewing prior work on template-haskell. - Exploring ways to make more libraries re-installable.
Lastly, let's not lose sight of:
- The Stability Working Group. - The GHC API Stability initiative from the HF.
Best, Moritz
On Fri, 29 Sept 2023 at 17:53, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Thank you for bringing us this far. I'd be happy to step up to drive
this further.
Thank you Moritz, that would be very helpful. I see the steps (*not *in dependency order) including
- Develop stability ideas for Template Haskell. I think we have agreed that it's a tricky case: widely used, but hard to stabilise - Develop a preliminary classification of language extensions, in partnership with the folk (who include Adam) working on the extension life cycle proposal <https://github.com/ghc-proposals/ghc-proposals/pull/601>. The preliminary spreadsheet <https://docs.google.com/spreadsheets/d/1sRIcNKdflX2ogrx2EF3vKOn0vmv-UEOdladBqtYXdaw/edit#gid=0>is helpful -- thank you Adam. Let's not duplicate this work! - Ditto for "experimental features". - Turn the Google doc into a GHC Proposal.
I see all this as the GHC counterpart to the GHC base-library proposal <https://github.com/haskellfoundation/tech-proposals/blob/main/proposals/accepted/051-ghc-base-libraries.rst>: our general goal is to make a clear boundary between "stable" and "experimental", so that:
- users know when they are moving into experimental land - developers know when they risk breaking stable code
While the boundary is unclear, misunderstandings arise in both directions.
Simon
On Thu, 28 Sept 2023 at 13:39, Moritz Angermann < moritz.angermann@gmail.com> wrote:
Simon,
Thank you for bringing us this far. I'd be happy to step up to drive this further.
I will say that I do see the tension you see as well. And I do believe if we come to a conclusion on this stability policy that it will make GHC development more rigorous, which I think is a good thing for all of us, not just the consumers of the compiler. I think we need to stay mindful that we can still freely experiment on the --std=experimental (or however that flag ends up being named) side. I see this whole discussion as leading us towards the language research reactor side of GHC being primarily confined behind --std=experimental, and the stability seeking (commercial application?) on the other side.
I do not yet see how we can end up with the inability to change. We will just have a clearer process for _breaking_ changes. This does absolutely not mean we have to end up in a local optimum, or that we can not change. We can!
Unless someone speaks up who does _not_ want me to drive, this, I'm happy to start driving this discussion (including writing the proposals, starting next week).
Best, Moritz
On Thu, 28 Sept 2023 at 19:30, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Should we have a document (or better spreadsheet?) with a bullet > point for each experimental feature to be considered? I believe we need to > take into account that we can’t end up classifying most of todays Haskell > programs unstable. As such I’d like to propose that we’d add to each > features a counter for how much of hackage (as a proxy for real world > usage) uses the specific feature. >
I think that would be a helpful way to "ground" the discussion a bit more. (The spreadsheet should also give a preliminary classification of extensions, at least into stable/experimental.)
I'm running out of capacity to drive this debate, useful though it is. Does anyone else feel able to drive some of the legwork?
So far this is all informal committee discussion. The next step would be a GHC Proposal inviting broader feedback from the community. I'm just hoping that by debugging it between ourselves we can side-step some unproductive discussions in that bigger context.
I believe we need to take into account that we can’t end up > classifying most of todays Haskell programs unstable >
There is a tension here. If we say something is "stable" then we have to be super-careful about changing it. (That's the whole point.) And yet if the feature (like INCOHERENT) is a flaky "you are on your own" unsafePerformIO-like feature, I am axious about tying ourselves into an inability to change the behaviour of corner cases. I'm not sure how to resolve this tension.
Simon
On Thu, 28 Sept 2023 at 02:20, Moritz Angermann < moritz.angermann@gmail.com> wrote:
> I think we are moving in the right direction! I do see however the > tension rising on (2). And without being clear about (2), I don’t think we > can properly agree on (1). We can agree on (1) in principle, but we need to > clarify what we consider unstable/experimental, as a precondition to have > finale agreement on (1). Otherwise people might agree to (1), only to be > surprised by (2). For (3), I’d be happy to try to get my employer to > provide resources for the implementation of —std=experimental. > > Thusly I believe we should start to build a list of features we > consider sufficiently experimental that they should preclude an existing > Haskell program from being considered stable. This list for me contains so > far: > > - Linear Types > - Dependent Haskell > > Adam pointed out experimental backend and non-tire-1 platforms. I > tend to agree with this, but see this distinctly separate from the language > stability (outside of backend specific language extensions, e.g. JSFFI). > > Platforms/backends may be experimental but those are (safe for > specific lang exts) orthogonal to the Haskell code the compiler accepts. > > Should we have a document (or better spreadsheet?) with a bullet > point for each experimental feature to be considered? I believe we need to > take into account that we can’t end up classifying most of todays Haskell > programs unstable. As such I’d like to propose that we’d add to each > features a counter for how much of hackage (as a proxy for real world > usage) uses the specific feature. > > Best, > Moritz > > On Wed, 27 Sep 2023 at 10:35 PM, Simon Peyton Jones < > simon.peytonjones@gmail.com> wrote: > >> it's essential that we continue to have these discussions to ensure >>> we're making the best decisions for the project and our community. >>> >> >> Yes exactly! Its tricky and nuanced; hence trying to articulate >> something in a concrete doc, so we are all on the same page (literally!). >> >> However, deprecation cycles don't mean we're averse to major >>> changes. It means we introduce them responsibly. When we believe a superior >>> design is possible, we can start a deprecation process to transition >>> towards it. >>> >> >> I have tried to make this explicit in Section 4. See what you >> think. >> >> I think there are three phases >> >> 1. Agree this document. Is it what we want. >> 2. Categorise extensions into stable/experimental, and identify >> experimental language features. >> 3. Implement --std=experimental (Section 6). >> >> (1) is what we are doing now. (2) will be some work, done by us. >> (3) is a larger task: it will require significant work to implement, and >> may impose unwelcome churn of its own. But that should not stop us doing >> (1) and (2). >> >> Simon >> >> - >> >> >> On Wed, 27 Sept 2023 at 10:20, Moritz Angermann < >> moritz.angermann@gmail.com> wrote: >> >>> Dear Adam, >>> >>> Thank you for your thoughtful feedback. I understand your >>> reservations, and it's essential that we continue to have these discussions >>> to ensure we're making the best decisions for the project and our >>> community. Let me address each of your points in turn: >>> - Cognitive Overhead for Users: >>> I understand the concern about cognitive overhead due to the >>> inability to remove complexity. However, our primary intention is to ensure >>> a gradual transition for our users rather than abrupt shifts. Introducing >>> changes via deprecation cycles allows users to adjust to modifications over >>> time, reducing the immediate cognitive load. It's a balance between >>> stability and simplicity, and I believe this approach allows us still to >>> reduce complexity. >>> >>> - Maintenance Burden in the Compiler: >>> Maintaining backward compatibility does indeed introduce some >>> overhead. Still, it also encourages a more disciplined and considered >>> approach to changes. With our deprecation cycles in place, it's not that we >>> never remove complexity; rather, we do it in a way that provides ample time >>> for adjustments. This benefits both the development team and the community. >>> >>> - Risk of Local Optimum: >>> This is a valid concern. However, deprecation cycles don't mean >>> we're averse to major changes. It means we introduce them responsibly. When >>> we believe a superior design is possible, we can start a deprecation >>> process to transition towards it. The flexibility and duration of our >>> deprecation cycles can be tailored depending on the severity of the >>> breaking change. >>> >>> - Discouraging Volunteer Contributors: >>> I understand that lengthy approval processes can be off-putting. >>> But it's crucial to note that a rigorous process ensures the consistency >>> and reliability of our project. We always welcome and value contributions. >>> Moreover, I believe this stability policy will provide us with clear >>> guardrails on how changes can be contributed. >>> >>> I will not disagree on the costs. I do believe though that the >>> costs for _breaking_ changes in the compiler ought to be borne by the >>> people making the change, instead of those who use the compiler (and may >>> not even benefit of those changes that caused breakage). I also see the >>> team maintaining GHC as the one to enforce this; they are the ones who cut >>> the releases. The fact that we may have breaking changes due to _bugs_ is >>> covered explicitly in the stability policy document. >>> >>> With my CLC hat on, I have been focusing on the same stability >>> guidelines as well (if it breaks existing code, I have been against those >>> changes without deprecation policies). The issues with the >>> template-haskell, and ghc library are noted. For the ghc library the >>> question will remain if we intent to provide a stable api to the compiler >>> or not. I believe many tools would like to have one, and if we relegate >>> anything unstable to ghc-experimental this might be achieved. For >>> template-haskell this is a bigger concern. Maybe we can collectively come >>> up with a solution that would allow us to provide a more insulated template >>> haskell interface from the compiler. >>> >>> However for template-haskell we might also need to look at what >>> exactly caused those breaking changes in the past. >>> >>> What this document outlines (in my understanding) is that any >>> experimental feature development can _only_ be visible behind >>> --std=experimental, and the dependency of ghc-experimental. Unless those >>> are given, the compiler should accept existing programs. This should allow >>> us enough room to innovate (everyone is always free to opt-in to bleeding >>> edge features with --std=experimental). I also believe that most of what >>> we have today will need to be treated as non-experimental simply because we >>> did not have that mechanism before. We don't want to break existing >>> programs as much as possible, thus relegating existing features into >>> --std=experimental (except for some fairly clear ones: e.g. Dependent >>> Haskell, and Linear Types?) is not really possible. What we can however do >>> is start deprecation phases for a few versions, moving features we consider >>> highly experimental (or maybe even bad) into `--std=experimental`. Just by >>> having deprecation phases and given the ecosystem enough time to adjust >>> (and provide feedback) we might come to different conclusions. >>> >>> As I've also outlined in the document, _if_ GHC was trivially >>> swappable, companies like IOG would _love_ to try new compilers and report >>> back bugs and regressions. As it is today, we can't. Making a large live >>> codebase compatible with 9.8 is a multiple weeks effort. Experimenting with >>> nightlies is technically impossible. _If_ I could setup the built of our >>> software trivial with ghc nightlies, I'd be _happy_ to build the >>> infrastructure out it to provide performance regressions (compilation, >>> runtime, ...) for our codebase and provide the feedback to the GHC team; >>> however I can't. And thus I'm stuck patching and fixing 8.10, and 9.2 >>> today. 9.6 maybe soon, but likely at the point in time where 9.6 is not >>> going to see any further releases, so I can spare trying to even forward >>> port my patches to HEAD. Not that I could even test them with head >>> properly, as our source is not accepted by HEAD. Thus I end up writing >>> patches against old stale branches. This to me is a fairly big >>> discouragement from contributing to GHC. >>> >>> Best, >>> Moritz >>> >>> On Mon, 25 Sept 2023 at 15:17, Adam Gundry <adam@well-typed.com> >>> wrote: >>> >>>> I'm afraid that I'm somewhat sceptical of this approach. >>>> >>>> A strong stability guarantee is certainly a valuable goal, but it >>>> also >>>> comes with costs, which I'd like to see more clearly articulated. >>>> Some >>>> of them include: >>>> >>>> * Cognitive overhead for users, because of the inability to >>>> remove >>>> complexity from the design. >>>> >>>> * Increasing maintenance burden in the compiler, because of the >>>> additional work needed to implement new features and the >>>> inability to >>>> remove complexity from the implementation. >>>> >>>> * A risk of getting stuck in a local optimum, because moving to >>>> a >>>> better design would entail breaking changes. >>>> >>>> * Discouraging volunteer contributors, who are much less likely >>>> to >>>> work on a potentially beneficial change if the process for >>>> getting it >>>> approved is too onerous. (I'm worried we're already reaching that >>>> point >>>> due to the increasing burden of well-intentioned processes.) >>>> >>>> Ultimately every proposed change has a cost-benefit trade-off, >>>> with risk >>>> of breakage being one of the costs. We need to consciously >>>> evaluate that >>>> trade-off on a case-by-case basis. Almost all changes might break >>>> something (e.g. by regressing performance, or for Hyrum's Law >>>> reasons), >>>> so there needs to be a proportionate assessment of how likely >>>> each >>>> change is to be damaging in practice, bearing in mind that such >>>> an >>>> assessment is itself costly and limited in scope. >>>> >>>> It seems to me that the GHC team have taken on board lessons >>>> regarding >>>> stability of the language, and the extension system already gives >>>> quite >>>> a lot of flexibility to evolve the language in a >>>> backwards-compatible >>>> way. In my experience, the key stability problems preventing >>>> upgrades to >>>> recent GHC releases are: >>>> >>>> * The cascading effect of breaking changes in one library >>>> causing the >>>> need to upgrade libraries which depend upon it. This is primarily >>>> under >>>> the control of the CLC and library maintainers, however, not the >>>> GHC >>>> team. It would help if base was minimal and reinstallable, but >>>> that >>>> isn't a total solution either, because you'd still have to worry >>>> about >>>> packages depending on template-haskell or the ghc package itself. >>>> >>>> * Performance regressions or critical bugs. These tend to be a >>>> significant obstacle to upgrading for smaller commercial users. >>>> But >>>> spending more of our limited resources on stability of the >>>> language >>>> means fewer resources for resolving these issues. >>>> >>>> There's surely more we can do here, but let's be careful not to >>>> pay too >>>> many costs to achieve stability of the *language* alone, when >>>> stability >>>> of the *libraries* and *implementation* are both more important >>>> and >>>> harder to fix. >>>> >>>> Adam >>>> >>>> >>>> On 22/09/2023 10:53, Simon Peyton Jones wrote: >>>> > Dear GHC SC >>>> > >>>> > To avoid derailing the debate about -Wsevere >>>> > < >>>> https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003407.html>, >>>> and HasField redesign < >>>> https://mail.haskell.org/pipermail/ghc-steering-committee/2023-September/003383.html>, >>>> I'm starting a new (email for now) thread about stability. >>>> > >>>> > I have tried to articulate what I believe is an evolving >>>> consensus in >>>> > this document >>>> > < >>>> https://docs.google.com/document/d/1wtbAK6cUhiAmM6eHV5TLh8azEdNtsmGwm47Zulga... >>>> >. >>>> > >>>> > If we converge, we'll turn that into a proper PR for the GHC >>>> proposal >>>> > process, although it has wider implications than just GHC >>>> proposals and >>>> > we should share with a broader audience. But let's start with >>>> the >>>> > steering committee. >>>> > >>>> > Any views? You all have edit rights. >>>> > >>>> > I think that the draft covers Moritz's and Julian's goals, at >>>> least that >>>> > was my intention. I have pasted Moritz's last email below, for >>>> context. >>>> > >>>> > Simon >>>> > >>>> > >>>> > ========= Moritz's last email ============ >>>> > >>>> > Now, this is derailing the original discussion a bit, and I'm >>>> not sure >>>> > how far we want to take this. But, regarding @Simon Marlow >>>> > <mailto:marlowsd@gmail.com>'s comment >>>> > >>>> > This is one cultural aspect of our community I'd like to >>>> shift: the >>>> > expectation that it's OK to make breaking changes as long >>>> as you >>>> > warn about >>>> > them or go through a migration cycle. It just isn't! (and I >>>> speak as >>>> > someone who used to make lots of changes, I'm now fully >>>> repentant!). >>>> > That's >>>> > not to say that we shouldn't ever change anything, but when >>>> > considering the >>>> > cost/benefit tradeoff adding a migration cycle doesn't >>>> reduce the >>>> > cost, it >>>> > just defers it. >>>> > >>>> > >>>> > I actually read this as we should stop having breaking changes >>>> to begin >>>> > with. And _if_ we >>>> > do have breaking changes, that deprecation does not change the >>>> need to >>>> > actually change >>>> > code (cost). As outlined in my reply to that, and @Richard >>>> Eisenberg >>>> > <mailto:lists@richarde.dev>'s observation, it >>>> > "smears" the cost. The--to me--_much_ bigger implication of >>>> deprecation >>>> > cycles is that we >>>> > _inform_ our _customers_ about upcoming changes _early_, >>>> instead of >>>> > _after the fact_. We >>>> > also give them ample time to react. Being by changing their >>>> code, or >>>> > raising their concerns. >>>> > Would the Simplified Subsumptions / Deep Subsumptions change >>>> have looked >>>> > differently? >>>> > As such I see deprecation cycles as orthogonal to the question >>>> if we >>>> > should have breaking >>>> > changes to begin with. >>>> > >>>> > Thus I believe the following: >>>> > >>>> > - Do have a deprecation cycle if possible. >>>> > - Do not treat a deprecation cycle as an excuse. Costs are >>>> deferred >>>> > but are as large as ever. >>>> > >>>> > >>>> > should be upgraded to: >>>> > - Preferably _no_ breaking changes. >>>> > - If breaking changes, then with a deprecation cycle, unless >>>> technically >>>> > infeasible. >>>> > - An understanding that any breaking change incurs significant >>>> costs. >>>> > >>>> > Ocaml recently added multicore support, and they put tremendous >>>> effort >>>> > into making >>>> > sure it keeps backwards compatibility: >>>> > >>>> https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md >>>> > < >>>> https://github.com/ocaml-multicore/docs/blob/main/ocaml_5_design.md >>>> > >>>> > >>>> > PS: we should also agree that a "stable" extension should >>>> not >>>> > require dependencies on ghc-experimental. To become >>>> stable, any >>>> > library support for an extension must move into `base`. >>>> > >>>> > >>>> > This seems like a good idea, however I still remain that >>>> _experimental_ >>>> > features should not be on-by-default in a stable compiler. Yes, >>>> ideally >>>> > I'd not even see them in a stable compiler, but I know this >>>> view is >>>> > contentious. The use of `ghc-experimental` should therefore be >>>> guarded >>>> > by `--std=experimental` as Julian suggested. That is a loud >>>> opt-in to >>>> > experimental features. >>>> > >>>> >>>> -- >>>> Adam Gundry, Haskell Consultant >>>> Well-Typed LLP, https://www.well-typed.com/ >>>> >>>> Registered in England & Wales, OC335890 >>>> 27 Old Gloucester Street, London WC1N 3AX, England >>>> <https://www.google.com/maps/search/27+Old+Gloucester+Street,+London+WC1N+3AX,+England?entry=gmail&source=g> >>>> >>>> _______________________________________________ >>>> ghc-steering-committee mailing list >>>> ghc-steering-committee@haskell.org >>>> >>>> https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee >>>> >>> _______________________________________________ >>> ghc-steering-committee mailing list >>> ghc-steering-committee@haskell.org >>> >>> https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee >>> >> _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
-- Arnaud Spiwack Director, Research at https://moduscreate.com and https://tweag.io.
On Fri, 13 Oct 2023 at 11:16, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
The mandate here is “make Haskell more stable” which is quite commendable,
but it's also very imprecise
Is it imprecise? I think our goal is pretty simple:* a program that compiles and runs with GHC 9.8 should also compile and run with GHC 9.10.* That's it. I think you subscribe to this as a general goal?
I fully subscribe to this goal.
Clearly that is a problem today: many users report that they are using years-old GHCs because the cost of upgrading to the latest version is so high.
Indeed. The General Rules I suggested at the start of this thread do no more than
articulate that goal, and give some general principles that we seek to follow. I think that does no more than make *explicit *our *implicit *way of working (we spend a lot of time on back-compat discussions). That is, nothing really new here, just making it more explicit.
Can you be more specific about what you don't like?
The general rules are perfectly reasonable. I'm much less enthusiastic about an `experimental` flag of sorts. But here's the thing: I claim that GR{1-3} aren't going to solve the stability problem. I'm confident about this because they're already the policy. And while it's not entirely impossible to imagine that writing them down more prominently will solve the problems that we have, I don't believe we should count on it. So anyway, we've been having this policy, have we failed to apply it? Why? Or maybe the reason why stability is a concern is because of reasons that aren't caught by this policy, then what is missing? I'm asking these questions in earnest: I really don't know. And I don't think we'll actually make significant progress without getting answers to these questions.
But here's the thing: I claim that GR{1-3} aren't going to solve the stability problem. I'm confident about this because they're already the policy. And while it's not entirely impossible to imagine that writing them down more prominently will solve the problems that we have, I don't believe we should count on it.
I agree. They won't solve it. (Incidentally, it's not just GR{1-3} but also the categorisation into stable/experimental, which GR{1-3} is predicated on.) But I think they will help. You are sceptical, but that's fine. We'll see. Provided they are not harmful [and I don't think you are saying that it is] we can just adopt them and move on. Completely-solving a complex, multi-faceted problem is hard. But that should not discourage us from making incremental progress towards that goal. The base-library splitting proposal (now agreed) is another piece of incremental progress that does not solve the problem, but will help. I am not against (in addition) trying to identify particularly painful problems in the past, and seeing what their root causes were. I just don't want to de-rail making incremental progress at the same time. I don't like to see you unhappy, Arnaud! Simon On Fri, 13 Oct 2023 at 10:38, Arnaud Spiwack <arnaud.spiwack@tweag.io> wrote:
On Fri, 13 Oct 2023 at 11:16, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
The mandate here is “make Haskell more stable” which is quite
commendable, but it's also very imprecise
Is it imprecise? I think our goal is pretty simple:* a program that compiles and runs with GHC 9.8 should also compile and run with GHC 9.10.* That's it. I think you subscribe to this as a general goal?
I fully subscribe to this goal.
Clearly that is a problem today: many users report that they are using years-old GHCs because the cost of upgrading to the latest version is so high.
Indeed.
The General Rules I suggested at the start of this thread do no more than
articulate that goal, and give some general principles that we seek to follow. I think that does no more than make *explicit *our *implicit *way of working (we spend a lot of time on back-compat discussions). That is, nothing really new here, just making it more explicit.
Can you be more specific about what you don't like?
The general rules are perfectly reasonable. I'm much less enthusiastic about an `experimental` flag of sorts.
But here's the thing: I claim that GR{1-3} aren't going to solve the stability problem. I'm confident about this because they're already the policy. And while it's not entirely impossible to imagine that writing them down more prominently will solve the problems that we have, I don't believe we should count on it. So anyway, we've been having this policy, have we failed to apply it? Why? Or maybe the reason why stability is a concern is because of reasons that aren't caught by this policy, then what is missing? I'm asking these questions in earnest: I really don't know. And I don't think we'll actually make significant progress without getting answers to these questions.
On Fri, 13 Oct 2023 at 11:53, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
But here's the thing: I claim that GR{1-3} aren't going to solve the
stability problem. I'm confident about this because they're already the policy. And while it's not entirely impossible to imagine that writing them down more prominently will solve the problems that we have, I don't believe we should count on it.
I agree. They won't solve it. (Incidentally, it's not just GR{1-3} but also the categorisation into stable/experimental, which GR{1-3} is predicated on.) But I think they will help. You are sceptical, but that's fine. We'll see. Provided they are not harmful [and I don't think you are saying that it is] we can just adopt them and move on.
Completely-solving a complex, multi-faceted problem is hard. But that should not discourage us from making incremental progress towards that goal.
I think there's a misunderstanding here, maybe it's due to the limitation of text communication, or maybe I'm just expressing myself very badly. I'm absolutely fine with enshrining GR{1-3}. I don't think there has been any discussion about them apart from minor rewordings.
The base-library splitting proposal (now agreed) is another piece of incremental progress that does not solve the problem, but will help.
I'm not confident about that. Last week, I even thought of a way it could hurt. We chose to name a bunch of things “Experimental” (rather than, say, GHC-specific), this carries the following risk: if features stay in the ghc-experimental package for too long, they may very well become part of “normal Haskell”. Programmers will start depending on it and will be habituated to understand that “experimental” really means “stable”, and we'll lose all the benefits of the scary warning on the tin. We need a very tight process if we're to make this work at all. I am not against (in addition) trying to identify particularly painful
problems in the past, and seeing what their root causes were. I just don't want to de-rail making incremental progress at the same time.
I sincerely hope I'm not doing that.
I don't like to see you unhappy, Arnaud!
Haha :D Thanks. You know what, I don't like seeing me unhappy either! (but I'm not in this particular case) On Fri, 13 Oct 2023 at 13:23, Simon Marlow <marlowsd@gmail.com> wrote:
It's already the policy in the sense that when we break stuff, we generally have a deprecation cycle. But where GR2 diverges from the current (informal) policy is in judging when it's OK to make a breaking change. GR2 - at least in my interpretation of it, and perhaps we should make this clearer - requires that to make a breaking change we have to be forced somehow. Because there's a bug that needs fixing, or because the current behaviour is broken for some reason. We're not going to make a breaking change just because the change would make things better, even with a deprecation cycle: those kinds of changes will still be possible, but they'll go behind a new language extension flag and/or into the next GHC20xx, so the user has control over when they have to adapt their code.
Maybe, though I actually don't have evidence that we've broken this policy, new or not, in the past. I hope you're right of course. Certainly a (somewhat implicit but real) change that has been brought by the conversations of the past few weeks is a reinforcement of the role of the GHC20xx languages. Let's see how much we can lean on this. It's probably true that a majority of the backwards compatibility issues
encountered with a GHC upgrade come from changes in third-party packages. But in order to decouple the compiler upgrade from package upgrades, we have to make all the existing packages compile with the new GHC, so stability has to start with GHC itself.
This gives support to Adam's idea of a reinstallable base. Incidentally I'd like the stability policy to be extended to compiler and
runtime flags - i.e. don't gratuitously change the behaviour of existing flags or remove them. Extend stability to build systems, not just code. This is much harder than language changes because we don't have extensions or GHC20xx, but we can do deprecation cycles.
This is reasonable, but do you have evidence that it's ever been a problem in the past? -- Arnaud Spiwack Director, Research at https://moduscreate.com and https://tweag.io.
I'm not confident about that. Last week, I even thought of a way it could hurt. We chose to name a bunch of things “Experimental” (rather than, say, GHC-specific), this carries the following risk: if features stay in the ghc-experimental package for too long, they may very well become part of “normal Haskell”. Programmers will start depending on it and will be habituated to understand that “experimental” really means “stable”, and we'll lose all the benefits of the scary warning on the tin. We need a very tight process if we're to make this work at all.
I am a bit more optimistic than you. - I expect that corporate users (Facebook, IOG, Standard Chartered, etc) will be strongly motivated to stick with the stable subset. - If they really want to use features labelled experimental they will push for them to be re-cateogised, because "experimental" means "much more liable to change without notice. - That in turn will develop a useful conversation. The alternative, of giving no guidance whatsoever about what is stable and what is not, seems noticeably worse to me. Simon On Fri, 13 Oct 2023 at 14:10, Arnaud Spiwack <arnaud.spiwack@tweag.io> wrote:
On Fri, 13 Oct 2023 at 11:53, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
But here's the thing: I claim that GR{1-3} aren't going to solve the
stability problem. I'm confident about this because they're already the policy. And while it's not entirely impossible to imagine that writing them down more prominently will solve the problems that we have, I don't believe we should count on it.
I agree. They won't solve it. (Incidentally, it's not just GR{1-3} but also the categorisation into stable/experimental, which GR{1-3} is predicated on.) But I think they will help. You are sceptical, but that's fine. We'll see. Provided they are not harmful [and I don't think you are saying that it is] we can just adopt them and move on.
Completely-solving a complex, multi-faceted problem is hard. But that should not discourage us from making incremental progress towards that goal.
I think there's a misunderstanding here, maybe it's due to the limitation of text communication, or maybe I'm just expressing myself very badly. I'm absolutely fine with enshrining GR{1-3}. I don't think there has been any discussion about them apart from minor rewordings.
The base-library splitting proposal (now agreed) is another piece of incremental progress that does not solve the problem, but will help.
I'm not confident about that. Last week, I even thought of a way it could hurt. We chose to name a bunch of things “Experimental” (rather than, say, GHC-specific), this carries the following risk: if features stay in the ghc-experimental package for too long, they may very well become part of “normal Haskell”. Programmers will start depending on it and will be habituated to understand that “experimental” really means “stable”, and we'll lose all the benefits of the scary warning on the tin. We need a very tight process if we're to make this work at all.
I am not against (in addition) trying to identify particularly painful
problems in the past, and seeing what their root causes were. I just don't want to de-rail making incremental progress at the same time.
I sincerely hope I'm not doing that.
I don't like to see you unhappy, Arnaud!
Haha :D Thanks. You know what, I don't like seeing me unhappy either! (but I'm not in this particular case)
On Fri, 13 Oct 2023 at 13:23, Simon Marlow <marlowsd@gmail.com> wrote:
It's already the policy in the sense that when we break stuff, we generally have a deprecation cycle. But where GR2 diverges from the current (informal) policy is in judging when it's OK to make a breaking change. GR2 - at least in my interpretation of it, and perhaps we should make this clearer - requires that to make a breaking change we have to be forced somehow. Because there's a bug that needs fixing, or because the current behaviour is broken for some reason. We're not going to make a breaking change just because the change would make things better, even with a deprecation cycle: those kinds of changes will still be possible, but they'll go behind a new language extension flag and/or into the next GHC20xx, so the user has control over when they have to adapt their code.
Maybe, though I actually don't have evidence that we've broken this policy, new or not, in the past. I hope you're right of course. Certainly a (somewhat implicit but real) change that has been brought by the conversations of the past few weeks is a reinforcement of the role of the GHC20xx languages. Let's see how much we can lean on this.
It's probably true that a majority of the backwards compatibility issues
encountered with a GHC upgrade come from changes in third-party packages. But in order to decouple the compiler upgrade from package upgrades, we have to make all the existing packages compile with the new GHC, so stability has to start with GHC itself.
This gives support to Adam's idea of a reinstallable base.
Incidentally I'd like the stability policy to be extended to compiler and
runtime flags - i.e. don't gratuitously change the behaviour of existing flags or remove them. Extend stability to build systems, not just code. This is much harder than language changes because we don't have extensions or GHC20xx, but we can do deprecation cycles.
This is reasonable, but do you have evidence that it's ever been a problem in the past?
-- Arnaud Spiwack Director, Research at https://moduscreate.com and https://tweag.io.
On Fri, 13 Oct 2023 at 10:39, Arnaud Spiwack <arnaud.spiwack@tweag.io> wrote:
But here's the thing: I claim that GR{1-3} aren't going to solve the stability problem. I'm confident about this because they're already the policy. And while it's not entirely impossible to imagine that writing them down more prominently will solve the problems that we have, I don't believe we should count on it. So anyway, we've been having this policy, have we failed to apply it? Why? Or maybe the reason why stability is a concern is because of reasons that aren't caught by this policy, then what is missing? I'm asking these questions in earnest: I really don't know. And I don't think we'll actually make significant progress without getting answers to these questions.
It's already the policy in the sense that when we break stuff, we generally have a deprecation cycle. But where GR2 diverges from the current (informal) policy is in judging when it's OK to make a breaking change. GR2 - at least in my interpretation of it, and perhaps we should make this clearer - requires that to make a breaking change we have to be forced somehow. Because there's a bug that needs fixing, or because the current behaviour is broken for some reason. We're not going to make a breaking change just because the change would make things better, even with a deprecation cycle: those kinds of changes will still be possible, but they'll go behind a new language extension flag and/or into the next GHC20xx, so the user has control over when they have to adapt their code. It's probably true that a majority of the backwards compatibility issues encountered with a GHC upgrade come from changes in third-party packages. But in order to decouple the compiler upgrade from package upgrades, we have to make all the existing packages compile with the new GHC, so stability has to start with GHC itself. Incidentally I'd like the stability policy to be extended to compiler and runtime flags - i.e. don't gratuitously change the behaviour of existing flags or remove them. Extend stability to build systems, not just code. This is much harder than language changes because we don't have extensions or GHC20xx, but we can do deprecation cycles. Cheers Simon
As I was saying in my previous email (I'm making a second email to avoid confusion between the serious process question and the more casual musing), I'd noticed that a lot of the migration issues are due to the base library changing. Maybe the CLC can have stronger stability policies but the truth is: it's pretty hard. The details of Haskell makes so many things backward incompatible: - It's incompatible to add a new instance for a type (somewhat mitigated by complaining about orphan instances, but orphan instances aren't always avoidable) - It's incompatible to add a member to a type class without a default implementation - It's incompatible to remove a member from a type class, even if the member is replaced by a simple function of the same name (see e.g. https://github.com/haskell/core-libraries-committee/issues/3 ) in - It's incompatible to add a function to a module because it may conflict with a function of the same name in another imported module (this isn't a theoretical concern: https://mail.haskell.org/pipermail/haskell-cafe/2023-October/136389.html ) There may be things that Haskell-the-language can do to help Haskell-the-ecosystem cope with some of these problems. So there may still be value in analysing the ways in which base or other libraries broke their downstream, and see how we can act. We can for instance consider the following issue of adding names: this isn't specific to Haskell in any way, but maybe it happens more to Haskel because we idiomatically import everything in the global namespace. This is one of the reasons why I care a lot about the Local Module proposal, by the way https://github.com/ghc-proposals/ghc-proposals/pull/283 .
participants (7)
-
Adam Gundry -
Arnaud Spiwack -
Chris Dornan -
Moritz Angermann -
Richard Eisenberg -
Simon Marlow -
Simon Peyton Jones