Informal discussion about the progression of `base`

Almost? If the packages were also automatically available to runhaskell/ghci/etc—so that we could always depend on them and use them for one-off scripts with no .cabal file—then it would behave the way I’d want.

At that point, though, it seems like we end up with a standard library that happens to be split over multiple packages under the hood. What’s the advantage there? Backwards compatibility? More flexibility around releases and versioning? (Honestly, I could see just those two being enough as long as we can make it work seamlessly in all our tooling.)

1 Like

I want to rip out lazy IO out of base and possibly replace it with proper streaming.

This might be a pipe (lol) dream, but anyway.

6 Likes

More like a “pipes” dream :wink:

Streaming is a tricky thing because there are so many different designs floating around for a core streaming abstraction, but it also seems critical because streams are such a foundational interface type. Lots of APIs naturally want to be streaming, but today that means needing to buy into one specific streaming library at the expense of the others. Not ideal if you’re trying to write a general-purpose library and minimize your dependencies.

2 Likes

The problem is that the [packages’] authors would have to go and update [their] projects to keep in sync.

That is true, but at least they would have a ready-made patch - it would be an exercise in “lessening friction”, rather that trying for “no friction at all” (another example of seeking “good” over “perfect” :-).

*It would be done already if it was a wanted one.

Other chores like swatting bugs and and keeping up with the Glasgow Haskell Change-a-thon could also distract from switching to Text - there are only some many hours in each day…

1 Like

…(heh) much like That Formerly Known As FRP - I would have raised the same point if someone had suggested adding one of those packages or libraries to base (e.g. to make windowing, GUI, etc tasks easier).

I want to rip out lazy IO out of base […]

Perhaps some “sample patches” to exemplify the alternatives would be of use in your quest: you can start with the hedis package and its use of that dastardly-lazy IO :-D

But you can already write “one-off scripts with no .cabal file”, right?

Yes: https://cabal.readthedocs.io/en/stable/getting-started.html#run-a-single-file-haskell-script

Huh, yeah, I guess you’re right. I’m pretty sure I had seen that before, but didn’t remember it. That’s definitely better than not having the option. It’s still not particularly discoverable, so it’s pretty bad for beginners: they’d need to add some special boilerplate just to have access to basic types.

But, to @tomjaguarpaw’s point, we could address that by using the same mechanism to provide more packages by default rather than absolutely needing to merge everything into base.

1 Like

While I think of it: given how special base is to GHC, and that it’s non-upgradeable, put me down for being in favour of as small a base as possible, and better user education around common libraries so that depending on common packages like text and containers doesn’t seem scary to them.

4 Likes

I wish we had vector in base, it is more commonplace and better than Array in base yet Array still has the special status. Vector in base with appropriate special treatment would be great. (The only reason I would use OverloadedLists extension is just for vector, same as OverloadedString for text)

2 Likes

2 posts were split to a new topic: Using more packages by default

This is getting off topic - my main concern is with the base library. Project customization comes in at a later step.

What I want to know is: which direction is most favoured by the community in terms of the base API? Should we invest the effort into merging base and text? If we do, I’d want to do more than just a glorified re-export. I want to see Read/Show using Text. I want fromString to become fromText, and I’d even go as far as making Text the default type of string literals, with my magic wand. This is the sense I’ve been getting from this thread: String was a mistake, and we should invest in fixing it, even if it means – heaven forbid! – straying yet further from the ancient Report.

4 Likes

That’s fair, though I think what has come to light is that everyone has good diverging ideas on things that should be included by default in base, and that to fulfill that using more packages by default seems like the right solution (at least I and @tomjaguarpaw lean towards it), more so than progression in base.

(Except for text, which would have far reaching consequences when merged into base and preferred over String which seems to generally agreed upon here)

Could a mod could split the above “idea” comment over to its own post? A separate discussion does seem better to discuss that concrete proposal, and whether it should be acted upon.

1 Like

I prefer to think of String (and for that matter, the ol’ monomorphism restriction) more as temporary “scaffolding” - there were good reasons in the past for having them in order to get Haskell "up and running". But now each have served their purpose, so it’s probably time to remove them.

Haskell 2010 retired the monomorphism restriction (n+k) patterns; perhaps e.g. Haskell 2024 can just retire String in favour of Text - as you eluded to, that one change by itself would be quite substantial:

  • I want to see Read/Show using Text

    Agreed.

  • I want fromString to become fromText

    …along with replacements for getStr, the putStrs (and yes; even the likes of error - no “scope creep” please!)

  • […] I’d even go as far as making Text the default type of string literals

    Definitely YES! That could make the first step in switching to Text as simple as:

    sed 's/\<String\>/Text/g'
    

    …as opposed to trying to prefix many and varied type signatures with Str (like Num) IsString.


So much for memory! I thought H2010 also dropped the MR - perhaps I was looking at a draft version? ;-/

split base

3 Likes

Honestly, I think something like this may be a way forward, for one critical reason - it sidesteps the issue of asking the conflicting questions of whether things should be added (base is too small) or things should be removed (base is too big), in favor of a way that acknowledges both.

Breaking base up into smaller components and then using flags (or some other method) to control and conditionally prune or include components would allow for a chosen set of default components to form the canonical base, while also allowing for default components to be pruned out, and optional components to be included, making it easier to experiment with changes and for base to be extended.

Then base can be published much as-is, plus a minimal base-slim and a maximal base-all, and anything more specific than this is honestly probably worth doing yourself.

2 Likes

This is exactly why I mentioned splitting base above (and later on, in private conversation with @Kleidukos) as a potential solution to these problems. I’m really hopeful that it would allow something like this to be achieved.

2 Likes
`PartialEq` & `PartialOrd`, superclasses of `Eq` & `Ord`.

At that point we might as well have TotalEq & TotalOrd, superclasses of Eq & Ord.

Coming from Rust, I miss the From and TryFrom traits.
The witch package provides a direct equivalent, so I usually start from Relude and add this on top of it.

Coupled with ViewPatterns it lets you write polymorphic code in such a convenient way:

doThingWithTimestamp :: From t UTCTime => t -> SomeRecord
doThingWithTimestamp (into -> utcTime) = _

I wish we had a standardized way to perform conversions like the Rust ecosystem has.

2 Likes