I would jump to a bigger, safer and more beautiful prelude at once. And I would most like it to be called base-5
.
* * *
The good note that there are different classes of use cases has already been given and I think it is essential that we spell these classes out. The simplest is the dichotomy of libraries and applications — I am going to consider it presently. Another note to keep in mind is that the purpose of a prelude is twofold: to enable presence and to advertise absence.
Examples.
If I am writing a pure library for munching big data:
-
There is really no point for me in having potentially useful data structures dispersed across many packages. I would rather have all of them at hand. Enable me to use the best tool for the job by default.
containers
kind of does the right thing here, and it should be pushed farther. -
At the same time, I would rather not have anything to do with IO, Template Haskell and
unsafeCoerce
in this library, and I would like to be enabled to advertise that. The more features I can advertise not having — the better.
If I am writing an application:
-
I may need streaming, concurrency, error handling, an effect system… Some of these are represented by many nearly indistinguishable choices. I would like to have a starter pack that makes the safest and the most approachable choice for me.
rio
is a kind of prelude that makes steps in this direction, choosing the effect system ofReaderT IO
for you, among other things. -
I would like to advertise the absence of unsafe functions.
For a bad example,
vector
is not something I would like to use since it makes no effort to provide a total interface. Or, for that matter,base
!For a good example,
protolude
exports only a single unsafe functionpanic
that emits a warning upon being compiled — this means that a combination ofprotolude
and-Wall -Werror
is a guarantee that only safe primitives are used.
Commons.
This gets us to a category common to everyone: obsolete things that should go away. base
has too many of them.
- Why do we have
String
inbase
, when there isbytestring
andtext
? - Why do we have lazy IO in
base
, when it is known to be problematic and there are many good alternatives, such as the conceptually simpleio-streams
? - Why do we have ports of C libraries in
base
, such asprintf
andgetOpt
, when we have libraries that do the same in a type safe way? - Why do we have unsafe functions like
head
inbase
when pattern matching is the «killer feature» of Haskell?
The list goes on.
There should be a process for throwing obsolete things away, lest we drown. There is no hiding behind «blessed» alternative preludes from this. All of us need a base
that we can be proud of, that shows the best of Haskell.