-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Clarify the situation around Data.List #22
Comments
We briefly discussed the issue on one of CLC meeting back in October. According to @chessai, CLC has approved monomorphisation of Since there is no agreed and voted migration plan, besides a draft discussed between @chessai, @emilypi and @bgamari, GHC developers may revert the change from GHC HEAD for now. CLC will work on migration plan, but it is likely to take time and will not happen overnight. We will communicate it to GHC developers and to the community when ready. |
I'm fine with the plan above -- though it sounds like "We will communicate it ..." suggests that the CLC is going to set up a migration plan without community input. Maybe that's fine: we, as a community, do not tend to address issues like this efficiently. But I want to speak up to say we can make this less painful by adding a new feature to the language: narrowing re-exports. I will illustrate with an example: module Poly ( id ) where
id :: a -> a
id x = x module Mono ( id :: Int -> Int ) where
import Poly module A where
import Poly
x = id 'x' -- accepted
y = id undefined -- accepted; y :: forall a. a is inferred module B where
import Mono
x = id 'x' -- rejected: id has type Int -> Int
y = id undefined -- accepted; y :: Int is inferred module C where
import Mono
import Poly
x = id 'x' -- accepted
y = id undefined -- accepted; y :: forall a. a is inferred The idea is that an export list can narrow the type of an export. If only the narrowed type is imported, that's the type of the identifier. If the narrowed type and the original type are both imported, then the identifier has the original type. If two different narrowed types are imported, a use of the identifier is rejected as ambiguous (not exemplified above); one could imagine some scheme looking for a more general type, but I think that's more complicated than it's worth. Using narrowing re-exports,
Compared to the plan to make Narrowing re-exports might be useful elsewhere, though it's not clear quite how useful they would be. Is the benefit here worth the cost? It's not clear to me. If this narrowing re-exports feature were very widely applicable, that would be exciting... but I don't think the feature would be used much. So it does seem like a largish language-level change for a smallish use case. I wanted to float the idea, regardless, to see if anyone else thought it a better way forward. |
Sorry that it made such impression. This was a mere statement that CLC is responsible to get it done, not that it will work on it behind closed doors.
Given that |
As discussed on the last CLC meeting back in February, current intention is to proceed with the migration plan as described in #22 (comment). However, given that this is a breaking and disruptive change, we would like to seek community's feedback on the proposed approach. The floor is open, please be civil. |
But what actually are the proposed changes? I mean, I can guess, but others less familiar with the situation may have no clue. Can we link to an accepted proposal or at least a statement of the proposal and some discussion? (Since the proposal predates the current GitHub-based CLC process I suppose the link would be to a mailing list archive.) Although I can guess what this proposal means I don't know who proposed it, what arguments were made for and against and why the decision was made as it was. I found some justification but it would be good to have that fleshed out. I apologise if I've missed the obvious here, but I've been clicking between the GitHub and GitLab issues trackers for five minutes without gaining clarity. |
@tomjaguarpaw the change is in https://gitlab.haskell.org/ghc/ghc/-/merge_requests/5304 |
why would you monomorphize data.list ? |
@jappeace the justification, used by the previous composition of CLC, is here: https://gitlab.haskell.org/ghc/ghc/-/issues/20025#note_365364 |
Nice, thanks, makes sense. 👍 |
Is it likely that changing imports for the affected bindings from |
Yes, except if you actually use list specific functions like import Data.List to import Data.Foldable (foldl')
import Data.List (sort) or import Data.Foldable (foldl')
import qualified Data.List as L
... sort to L.sort... |
Please don't do this. These sorts of "cleanup" changes make perfect sense in ones own personal packages, but not for a package like I'm an application developer, and the first step for me when evaluating the amount of work required to create a Haskell application is to go look for a package either on Hackage or (more often) on GitHub that does what I want. I very often find some old Haskell library on GitHub that does what I want but hasn't been updated in several years. Changes like the one suggested here increases the amount of work needed to use libraries like these, thus directly increasing the amount of work associated with developing applications in Haskell compared to other languages that have more users and therefore more libraries that remain maintained years down the road. Also, importantly, I would like to point out that the practice of having the CLC produce patches for the newest version of the affected packages because of a breaking change to Consequently, if the CLC is genuinely interested in shifting to themselves the burden created by backwards-incompatible changes to
To be clear, I'm not categorically against breaking changes to |
@runeksvendsen You might be interested in https://discourse.haskell.org/t/pre-hftp-ghc-x-hackage-a-tool-for-easing-migrations-to-new-ghc-versions/4239 / https://github.com/bgamari/tech-proposals/blob/ghc-x-hackage/proposals/001-ghc-x-hackage.md I want this change, and for me the breakage you describe is real but also a pointless tragedy. The above proposal is a very good stop-gap solution to this; the breakage this causes is quite trivial to fix, and so if we can crowd-source fixes to each other's packages it should be not to hard to fix the issues. But this should also be but the first step, there are many more thing we can do such as support the old and new One argument might be to fix make the solutions, then agree to do the breakage. (Remember, there is still a deprecation cycle here.) That sounds nice, but history doesn't pain this method in a good like, because the vast majority of languages to avoid breakage until tools are available just end up stagnating (See https://twitter.com/__phantomderp/status/1510309539538690055 and really @ThePhD's entire mission with C.) So given the bias towards stagnation, affirming decisions like this, with long road maps, while concurrently making better tools to deal with cruft and breakage and hopefully accelerate those timelines, I think is the only path forward. It may not have much precedent, but at least it doesn't have precedent of failure. |
I wonder why @runeksvendsen is the only person so far asking for long-term backwards compatibility. Are there no others that want it? Do they not know of this discussion? [1] Do they want it, and know of this discussion, but they're too burnt out arguing against breaking changes? Personally I like cleaning things up, and this change will probably cause me personally some breakage, but not too much. On the other hand, I don't like the idea that the people who are going to be most resentful of this change are just too frustrated to participate. How can we work out if there are such people and if so, encourage them to participate? [1] It has been posted on Reddit at least, and I posted it on Twitter. |
I think backwards compatibility is important. But it's more important to fix API design issues like |
FYI: I have reached out to Graham Hutton (@GrahamHutton) and Erik Meijer (@headinthebox) on Twitter (https://twitter.com/runeksvendsen/status/1510526460162940931), urging them to voice their opinion in this thread, because we share views on #3 and I'm interested in hearing whether this extends to this issue. |
@runeksvendsen I completely disagree that the situation with The surprising polymorphism of functions like |
@sjakobi note that |
I know. I hope that |
There is a backwards-compatible alternative: add a new module |
What would happen to For now I can use |
Not forever, just for a while. The sequence of states could look something like
The situation proposed in this thread seems to be a particular instance of this scheme, whereby 2, 3, and 4 are collapsed. I'm pointing out that we don't have to collapse them. We can add some delay between 2 and 3 and between 3 and 4, three releases seems reasonable, off the top of my head, but other amounts of delay are possible. On the other hand, perhaps doing it in one "big bang" to get it over with is more desirable. |
Given the recent sensitivity about breaking changes, i would go for the progressive way (assuming there would be breaking changes at any level) We even could add a |
Would it be possible to add a warning for non-list usages of Data.List functions before the actual change is made? |
I think this is the intention of step 2 in the original post
|
@tomjaguarpaw ah, thanks, I missed that |
My impression is that this more gradual scheme would lead to more breaking changes not less (as we are introducing then removing a new module). A nice thing about fixes to accommodate making I also doubt that users of This was implied by sjakobi's comment, but such a module already exists in the form of
|
There is a non-breaking way to proceed, as I outline above. It would require a new language feature, allowing a module to re-export an identifier with a more specific type. I think that it's a sound language feature -- the only question (to me) is whether there are use-cases beyond the update to |
Perhaps I missed something in your suggestion @goldfiere, because I don't understand how it is non-breaking. Currently this is valid code Data.List.length (Just ()) I don't see how it can continue to be valid code after the proposed |
You're right, @tomjaguarpaw -- that would break. Indeed, we want that example to break, so the very essence of this move is to break code. What it wouldn't break is module X where
import Data.List
-- NB: Prelude is imported unqualified
... length (m :: Map k v) ... But your question highlights an aspect of this discussion that has remained implicit: precisely what breakage are we worried about? What breakage are we OK with? For example, if we're not OK with Tom's |
I'm in favor of @Bodigrim's proposal. Indeed, as I've written elsewhere, I think that changes to core tools [definition needed] should be released only when all libraries in Stackage have patches submitted. This is a lot of work, but the work is unavoidable -- the only question who does it. The policy here makes the proponents of the change responsible; not doing this makes arbitrary open-source authors (who may strongly disagree with the change) responsible. If you're going to agitate for a breaking change, then it seems appropriate for you to put in the muscle to make it palatable for others. (Perhaps we make an exception for security holes.) Regarding @konsumlamm's worry about Hackage vs Stackage: You make good points. But given that many Hackage packages are unmaintained or otherwise broken, it seems unnecessary to try to patch everything there. Stackage makes for a good middle ground. And note that patches for Hackage are seen as a necessary condition, not a sufficient one. That is, if every Stackage package breaks but has a patch, we probably still shouldn't merge. This would be decided on a case-by-case basis. If we are now discussing @Bodigrim's recent proposal, can I ask that it be made more prominent? In general, where do long-term CLC proposals live? It doesn't seem there's a convenient spot in this repo, but maybe I'm just misunderstanding something. In any case, as a community member, it would be great to have a canonical URL where we can all look to understand what is being proposed and whether that proposal has been accepted (and with what debate). Right now, this ticket still seems to be about the proposal summarized by @mpickering at the top. Thanks! |
@Bodigrim, @goldfirere I hope that CLC and GHC Steering committee (and whatever other committees & groups relevant) agree and adhere on that then. |
To be clear, @phadej, no one has agreed to that plan. Do not expect this to be adhered to. It's something I personally think is a good idea, but there has been no wide discussion in this direction. My take is that we can't promise this in good faith right now. First, we have to get GHC CI working generally, and have the head.hackage process working well. Then, we can start to tackle Stackage. The good news is that the impending arrival of Bryan as a GHC CI guru gives us reason to hope that we will get there, say, by the end of this year. Only once we have the technical infrastructure in a reasonable enough state to imagine doing this well would I try to push to make this a promise GHC makes to the world. |
@goldfirere Then, until there's infra to do things, CLC shouldn't ask patch sets for changes either. As practitioner I don't care if the breakage is due change in Instead, the valuable resource have been GHC migration guide (like there is for 9.4: https://gitlab.haskell.org/ghc/ghc/-/wikis/migration/9.4 and others https://gitlab.haskell.org/ghc/ghc/-/wikis/migration/9.2). I'm also sceptical about quality of patches if they were (mass)-produced. I repeat, I ask CLC to not ask for patches until there is alignment with all GHC stuff. E.g. I could claim that |
@phadej You're suggesting that the CLC and GHC should agree on our approach here. That sounds quite sensible to me. But I don't think we need to stop all potentially breaking changes until we have the Stackage plan worked out. It's just that each breaking change signals our unreadiness as an enterprise-level language, in proportion with how much breakage it causes. If we believe that the I, for one, think that the |
This proposal is accepted, see @Bodigrim comment #22 (comment) And the whole discussion is about getting community input for CLC to decide on migration plan. I think everything has been said already, so i'll wait for CLC to write down the plan. |
I would propose the following:
Now, at such a time as people feel comfortable "pulling the lever" on the actual changes to Data.List, they can be implemented. This may involve a patchset, this may involve more tooling with head.hackage, etc, or it may require something somewhat different. The outstanding questions are really about just what the criteria are for pulling the lever. But the next steps are the same regardless, and should proceed. |
That sounds good to me. While improved CI should obviate the criticality of |
See the recent reddit thread about breaking changes for why we need to tread extremely carefully here.. https://old.reddit.com/r/haskell/comments/ujpzx3/was_simplified_subsumption_worth_it_for_industry/ |
Here is my final proposal, slightly amended from above:
This plan puts the burden on the proponents of the change. If they wish to speed up the process, they can potentially start patching existing packages right now, not even waiting for GHC X.Y. On the other hand, if few people are interested to put their efforts into it, the change is likely to be delayed until a day when the majority of packages choose to comply with Dear CLC members, let’s vote on this migration plan. @tomjaguarpaw @emilypi @chessai @cgibbard @mixphix +1 from me. |
+1 |
2 similar comments
+1 |
+1 |
With 4 votes in favour out of 6 possible, the migration plan is approved. Thanks all. |
Presumably, there needs to be a GHC ticket tracking at least the first step of this plan? |
@ulysses4ever feel free to raise one. |
I think there is a step missing from the plan, namely, communicating about the breaking change to the community. Does the CLC have a blog or another platform which can be used to communicate about things like this? |
@mpickering I'll post on Reddit once #76 is merged. |
I'm trying to summarise the state of this proposal as part of my volunteering effort to track the progress of all
Please, let me know if you find any mistakes 🙂 @mpickering could you share a status update on the implementation and what are next steps? Also, please do let CLC know if you need any help, so we can coordinate and prioritise approved proposals accordingly! |
In https://gitlab.haskell.org/ghc/ghc/-/issues/20025 it was observed that the proposed changes to monomorphise Data.List were not well communicated with the community and many people were surprised at the change. It was therefore decided to revert the patch whilst the CLC proposals system was set-up, it has now been set-up so the CLC should decide on the plan for this issue.
The plan articulated by @chessai was as follows:
I am executing part 1 of this plan currently (https://gitlab.haskell.org/ghc/ghc/-/merge_requests/6409)
The new CLC need to agree to the rest of this plan and communicate the result with the community.
The text was updated successfully, but these errors were encountered: