haskell / core-libraries-committee

95 stars 16 forks source link

Data.List should re-export GHC.List.List #182

Closed Kleidukos closed 1 year ago

Kleidukos commented 1 year ago

Proposal

Data.List should re-export GHC.List.List

It is terribly awkward to have

import Data.List qualified as List
import GHC.List (List)

Impact Assessment

I'll fill out this part when I am able to compile the ghc-9.4.4 branch of GHC, for the moment I'm facing hardships with "missing dependencies".

simonpj commented 1 year ago

Why not? If I want magicDict (and I want it often enough), why can't look for a GHC specific thing in ghc-prim where it's defined? It's not like it being in ghc-experimental will make it any more stable, will it?

Yes, it will.

Stuff in ghc-experimental is at least a candidate for long term stability. We wil strive to keep that API stable, albeit not as vigorously as base.

But ghc-prim (in this new view of things) an entirely internal matter. It is full of sharp knives. There is no signal about what functions are stable functios that a user might reasonably rely on, and which are internal functions that might vanish at a moment's notice.

Everyone is welcome to depend on ghc-prim, and there are legitmate reasons to do so. But it is inadvisable to do so without good reason. If there is a useful function there, which you'd like to be part of GHC's stable API, then please encourage us to put it in ghc-experimental or base.

You are right about GHC.Exts, which predated all this. Over time, I hope we can give ghc-experimental a better structured API.

phadej commented 1 year ago

@simonpj naming a package with strong stability guarantees ...-experimental is not very intuitive.

simonpj commented 1 year ago

@simonpj naming a package with strong stability guarantees ...-experimental is not very intuitive.

That is a fair comment. Do you have a better suggestion? It's expermental in the sense that newly-minted GHC Proposal that define new types or functions are likely to expose them here.

Its stability guarantees are not strong; they are stronger than ghc-prim (which has none) but weaker than base.

ocharles commented 1 year ago

I think the name is fine, it just needs to be accompanied by clear prose outline what that stability guarantee is. Presumably it's something like "follows PVP, but we won't necessarily go through deprecation cycles" or something? It seems that people know of some sort of stability spectrum with ghc-prim at one extreme and base at the other. It would be nice to know what one can expect at these various points along this spectrum (that may have already been covered, in which case we can just summarise it and pop it in the documentation/README)

simonpj commented 1 year ago

I think the name is fine, it just needs to be accompanied by clear prose outline what that stability guarantee is

Great. It's all been evolving in the last few months, but once the dust settles I think it would be really good idea to document it very explicitly. Ping ghc-devs if you think that hasn't happened in the next month or three. (Summer break coming.)

s-and-witch commented 1 year ago

IMO, the idea of ghc-experimental can be easier replaced with a new pragma like deprecated, but for experimental functions/modules/exports. In that case, we can just let experimental functions live in base and require CLC proposal only for making them stable.

Similar to this proposal about extensions: https://github.com/ghc-proposals/ghc-proposals/pull/601

By doing things in this way, we will gain advantages that can't be reached (at least all of them) with the new ghc-experimental package: 1) Stable functions can be internally implemented via experimental ones (unless it may change stable function's behavior) 2) Unstable functions can use stable functions defined in base 3) No need to know about another new magic standard package that holds "unstable" functions.

UPD: We can use https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0541-warning-pragmas-with-categories.rst for this purpose, like {-# WARNING in "x-unstable" func "This is an unstable function." #-}

phadej commented 1 year ago

@ocharles

stability spectrum with ghc-prim at one extreme

But ghc-prim is extremely stable, I'd say a lot more stable than base!

simonpj commented 1 year ago

But ghc-prim is extremely stable, I'd say a lot more stable than base!

That may be so in practice, but if so it is by accident and not by design. You can't rely on it being stable.

But no one is going to ban you from importing it!

phadej commented 1 year ago

You can't rely on it being stable.

It follows PVP, and I doubt you will rename all the primops just for the sake of renaming.


What is the purpose of ghc-experimental, is it the staging library for inclusion into base?

Will primops be exported from ghc-experimental, will primops be included in base?

I think these are in conflict.

If ghc-experimental is a staging library for stuff which well (hopefully) eventually land in base, then primops doesn't belong there, as these will come and go.

And then I think, importing them from ghc-prim is the right thing to do. If I reach out for a primitive, I know that it may change in the next GHC version.

If on the other hand, ghc-experimental is a staging library, but also a library (re)exporting some GHC specific low-level stuff which is not intended to ever be in base, then there are two jobs for one library, and that is not great either. That's exactly the problem with current base, which tries to serve multiple jobs with conflicting interests.

AMEND: That's why I think ghc-prim is an excellent library. It has one job, it does it well.

tomjaguarpaw commented 1 year ago

A couple of observations:

  1. Discussions about ghc-experimental are not particularly relevant to this CLC proposal.
  2. Packages created by Team GHC are not the CLC's business in any case. Team GHC can make packages called ghc-prim, ghc-experimental and ghc-magic-unicorn and do whatever they want with them, and none of that impinges (directly) on the CLC.

So I think this discussion has gone way off topic.

Kleidukos commented 1 year ago

The following packages would be disrupted by such a change, thanks to serokell's hackage-search and clc-stackage:

acme-grawlix-0.1.0.2 curry-frontend-2.0.0 lorentz-0.15.2 streamly-0.9.0 streamly-core-0.1.0 Mapping-2.0.0.0 Top-1.7 cherry-core-alpha-0.5.0.0 hydrogen-prelude-0.20 kansas-lava-0.2.4.5 liquidhaskell-0.9.0.2.1 local-search-0.0.7 nri-prelude-0.6.0.6 spiros-0.4.2 rebase-1.19

rebase is the only one that raised an error related to Data.List.List during the running of clc-stackage.

I will happily submit PRs to these packages.

Bodigrim commented 1 year ago

@Kleidukos please prepare a set of patches sufficient to compile clc-stackage and publish it somewhere (as a repo of diffs, or as a GitHub organisation with a set of patches repos, or raise PRs to affected packagew). We would not be able to vote formally otherwise.

In the meantime I'd like to encourage CLC members to express their (non-binding) opinions on the proposal. @tomjaguarpaw @hasufell @parsonsmatt @angerman @chshersh @mixphix

parsonsmatt commented 1 year ago

I'm in favor.

Most of the packages above define type List = [] anyway.

mixphix commented 1 year ago

yes yes yes!

hasufell commented 1 year ago

I'm mostly indifferent. The only counter-argument I could see is that beginners might now be exposed to two ways of expressing lists, since it'll be much more prominent in Data.List. I don't know what people with more teaching experience have to say about this... @chshersh ?

tomjaguarpaw commented 1 year ago

I would be in favour.

chshersh commented 1 year ago

As a Haskell educator, I did notice that the [a] type notation for lists can be confusing to some people, and I'd rather prefer having List a instead (at least it's consistent with almost every other type in Haskell). Learning the type signature of lists is not the most difficult part of learning Haskell but it does introduce some minor difficulties and inconsistencies.

There's 30+ years of learning materials for Haskell that uses square brackets for lists, so I'm afraid it's too late to change the direction here. But I can imagine that some people might prefer using List in type signatures in their teaching materials and it might work well (as long as GHC itself uses List in compiler messages).

Generally, I don't think it'll hurt anyone to reexport List from base and Data.List. It does make things better as being an identifier that you can click in your IDE and actually go the definition and read the docs.

However, the existing docs for List are quite sparse. I'm afraid some Haskell beginners might get confused by going to the Data.List module and reading about List type while none of the tutorials mention it, and the source code uses [] everywhere.

I would support this proposal stronger if it added some documentation to the List type, specifically:

  1. What is the relation between [a] and List a? Would they work interchangeably? When one may prefer one signature over another?
  2. How to make GHC show List in compiler messages? What extensions / GHC flags to enable?
  3. Add examples using List in the type signatures.
  4. Add @since annotations (already discussed above).
  5. Haddock shows instance Monad List but when I go to the sources, I see instance Monad []. A sentence or two about any restrictions where List and [] can and can't be used would be great (a full exhaustive list would've been even better).
hellwolf commented 1 year ago

As a Haskell educator, I did notice that the [a] type notation for lists can be confusing to some people, and I'd rather prefer having List a instead

Just wanted to mention this, maybe it's still related: https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0475-tuple-syntax.rst

" Proposals https://github.com/ghc-proposals/ghc-proposals/pull/270, https://github.com/ghc-proposals/ghc-proposals/pull/281, https://github.com/ghc-proposals/ghc-proposals/pull/378, and https://github.com/ghc-proposals/ghc-proposals/pull/473 all struggle when faced with puns, the use of an identifier that can be interpreted either in the type-level namespace or the term-level namespace (but with different meanings). "

Bodigrim commented 1 year ago

From educational perspective, it is a common pedagogical technique to say "let's write our own list data List a = Nil | Cons a (List a)". E. g., I think "Programming in Haskell" by @grahamhutton does exactly this, and LYAH is the same, and many others:

I'm uneasy that all these resources will be invalidated by exporting Data.List.List.

dixonary commented 1 year ago

Why would they be invalidated by that?

If there are any printed resources which import Data.List unqualified and have no specified GHC that they are written for, then hopefully our modern compiler messages will make the problem obvious to a relative newcomer. If they don't then that's on us.

MangoIV commented 1 year ago

I do also agree from what I have seen in students at my uni that promoting less punning is worth more than the possibility of redefining something that already exists; I think the error messages for redefining are pretty readable and easy to solve, even for very beginners; I would even go a bit further and claim that they're one of the first error messages learners see. :D

Bodigrim commented 1 year ago

@dixonary the experience is that even non-printed resources are extremely unlikely to get updated.

I mean, this is not a blocker indeed. But I also see only marginal benefit from re-exporting List from Data.List. As long as we are not looking to deprecate the punning syntax any time soon, I personally don't see much point to promote non-punning one: having two names for the same thing is never good. It's already confusing that because of a Haddock bug, [a] and List a appear interchangeably in haddocks.

Bodigrim commented 1 year ago

@Kleidukos just a reminder that this is still blocked on impact assessment, which requires preparing specific patches, not just listing packages which are potentially affected.

Kleidukos commented 1 year ago

@Bodigrim yes! My computer's power supply has problems so I'm waiting for a new one, so that running clc-stackage can be done without problems. :)

Bodigrim commented 1 year ago

@Kleidukos if there is no progress within two weeks, I'll close as abandoned.

Kleidukos commented 1 year ago

@Bodigrim I should be able to give a proper patch list on Monday! :)

Kleidukos commented 1 year ago

Alright, I was actually wrong in my first observation, there are five patches needed:

In the last patch I toyed a bit with CPP, which is what should be expected of the final patches that I shall send to these packages once the version of base that will hold the new export will be known.

Bodigrim commented 1 year ago

Thanks @Kleidukos! Could you also point us to an MR with the proposed change? Sorry if you mentioned it already, I’m from mobile.

Kleidukos commented 1 year ago

@Bodigrim Sorry I believe I don't fully understand what you mean, if you are referring to concrete patches for the build problems, they are listed in my above comment (which is what I read I should do before approval, and then submit the patches to the packages after approval). Or perhaps are you thinking of a MR to head.hackage? Or did I really misunderstand the assessment section of the guide? (in which case I am sorry)

Bodigrim commented 1 year ago

All good with impact assessment, many thanks :) I'm talking about a draft GHC MR, adding the reexport (just two lines of changes and changelog, nothing fancy).

Kleidukos commented 1 year ago

Heavens, apologies for the evening brain. Sure, it's underway. :)

Kleidukos commented 1 year ago

MR created: https://gitlab.haskell.org/ghc/ghc/-/merge_requests/11426

Bodigrim commented 1 year ago

Dear CLC members, following the non-binding discussion above, let's vote on the proposal to re-export GHC.List.List from Data.List. The (trivial) MR is available at https://gitlab.haskell.org/ghc/ghc/-/merge_requests/11426 (disregard CI failures, they are inconsequential). The impact assessment is available above: just a few name clashes, which the proposer has patches ready to be submitted (and there are 6+ months until GHC 9.10 to incorporate the change).

@mixphix @hasufell @tomjaguarpaw @parsonsmatt @angerman @velveteer

hasufell commented 1 year ago

+1 under the condition that the documentation remarks raised here are taken care of

tomjaguarpaw commented 1 year ago

+1

Kleidukos commented 1 year ago

@hasufell Please see https://gitlab.haskell.org/ghc/ghc/-/merge_requests/11426, feedback would be welcome on the topic of documentation.

parsonsmatt commented 1 year ago

+1

Bodigrim commented 1 year ago

@mixphix @angerman @velveteer just a gentle reminder to vote.

velveteer commented 1 year ago

+1

mixphix commented 1 year ago

+1

Bodigrim commented 1 year ago

+0. I'm generally opposed to have two names for the same thing and reluctant to make sacrifices just for the sake of non-punning Dependent Haskell syntax. But given that it's List internally already, and both names resurface in documentation already, embacing the change might be a reasonable option.

Thanks all, there are enough votes of unconditional support to approve. Further documentation improvements, if any, do not require a CLC vote.

Kleidukos commented 1 year ago

Thanks everyone for your patience. :bow: