Skip to content

Commit a5eef41

Browse files
authored
Merge pull request #53 from simonpj/ghc-module-naming-2023
Module naming conventions for GHC base libraries
2 parents 461a1c2 + d5c938e commit a5eef41

File tree

1 file changed

+188
-0
lines changed

1 file changed

+188
-0
lines changed

proposals/0000-ghc-module-naming.rst

+188
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
.. sectnum::
2+
3+
**Module naming conventions for GHC base libraries**
4+
5+
Background and motivation
6+
===========================
7+
The accepted `Proposal #51: GHC base libraries <https://github.com/haskellfoundation/tech-proposals/blob/main/proposals/accepted/051-ghc-base-libraries.rst>`_
8+
defines the following libraries:
9+
10+
* ``base``:
11+
12+
* The foundational library on which the rest of the Haskell ecosystem is based.
13+
* Its API is carefully curated by the `Core Libraries Committee <https://github.com/haskell/core-libraries-committee>`_, and is kept rather stable.
14+
* Depends on ``ghc-internal`` (and ``ghc-prim`` etc), but *not* on ``ghc-experimental``.
15+
* Major version bumps are at the Core Libraries Committee's discretion.
16+
17+
* ``ghc-experimental``:
18+
19+
* The home of experimental extensions to GHC, usually ones proposed by the
20+
`GHC Steering Committee <https://github.com/ghc-proposals/ghc-proposals/>`_.
21+
22+
* Functions and types in here are usually candidates for later transfer into ``base``. But not necessarily: if a collection of functions is not adopted widely enough, it may not be proposed for a move to `base`. Or it could move to another library entirely.
23+
24+
* It is user-facing (user are encouraged to depend on it), but its API is less stable than ``base``.
25+
26+
* Depends on ``base``.
27+
28+
* Likely to have a major version bump with each GHC release.
29+
30+
* ``ghc-prim, ghc-internal`` (and perhaps others; it's an internal GHC implementation decision):
31+
32+
* Define functions and data types used internally by GHC to support the API of ``base`` and ``ghc-experimental``.
33+
34+
* These libraries come with no stability guarantees: they may change at short notice.
35+
* Certain to have a major version bump with every GHC release.
36+
37+
In addition we already have:
38+
39+
* ``ghc``: this library exposes GHC as a library, through the (currently ill-defined) GHC API.
40+
41+
All these libraries follow the Haskell Package Versioning Policy (PVP). The reader is encouraged
42+
to consult `Proposal #51: GHC base libraries <https://github.com/haskellfoundation/tech-proposals/blob/main/proposals/accepted/051-ghc-base-libraries.rst>`_ for more background and rationale for this library structure.
43+
44+
The question arises of *what module names should be used*. For example, suppose that all three exposed a module called ``Data.Tuple``. In principle that would be fine -- GHC allows you
45+
to use the package name in the ``import`` statement, to disambiguate. But it's *extremely* confusing. This proposal articulates a set of conventions to
46+
help us design module names.
47+
48+
The proposal
49+
============
50+
51+
This proposal is split into four sub-proposals for easier discussion. Each sub-proposal builds on the
52+
earlier ones -- they are increments, not alternatives.
53+
54+
The goals of this proposal are deliberately limited to establish naming conventions. We do not propose
55+
any changes to ``ghc`` or to ``cabal``.
56+
57+
Proposal 1
58+
-----------
59+
60+
* Modules in ``base``, ``ghc-experimental``, ``ghc-prim``, ``ghc-internal`` etc should all have distinct names.
61+
62+
That principle leads immediately to the question: what should those names be? Hence proposal 2.
63+
64+
Proposal 2
65+
-----------
66+
67+
* Modules in GHC's internal libraries (``ghc-prim``, ``ghc-internal`` etc) should be of form ``GHC.Internal*``.
68+
* Modules in ``ghc-experimental`` should be of form ``*.Experimental``.
69+
* Modules in ``base`` should not have either of these forms.
70+
71+
So example we might have
72+
73+
* ``GHC.Internal.Bits`` in ``ghc-internal``,
74+
* ``Data.Bits.Experimental`` in ``ghc-experimental``
75+
* ``Data.Bits``, and currently also ``GHC.Bits``, in ``base``
76+
77+
Why ``GHC.Internal.*`` for modules in ``ghc-internal``? Would ``GHC.*`` not be enough? Here's why:
78+
79+
* ``base`` already has ``GHC.Bits``, and Proposal 1 stops us re-using the same module name in ``ghc-internal``.
80+
If we were starting from a blank sheet of paper we might have no ``GHC.*`` modules in ``base``, but there
81+
curently 138 such modules and it seems unlikely that we will ever remove all, or even most, of them from
82+
``base``.
83+
84+
* The prefix ``GHC.Internal`` serves as an additional clue to the importing module that this API is not stable.
85+
86+
* Since ``ghc-internal`` is brand new, we can name its modules however we like. However, ``ghc-prim`` exists
87+
already and we may have to live with modules like ``GHC.CString`` in ``ghc-prim`` for a while. Perhaps
88+
we make the switch slowly over time, by introducing ``GHC.Internal.CString`` and deprecating ``GHC.CString``.
89+
90+
Note that among the GHC implementation packages (``ghc-prim``, ``ghc-internal``, ``ghc-bignum`` etc) there
91+
is no expectation that the module name signals which package the module is in. It's just an internal
92+
implementation matter.
93+
94+
Using a prefix for ``ghc-internal`` and a suffix for ``ghc-experimental`` may seem inconsistent,
95+
but it was a clear consensus from the discussion about the proposal:
96+
97+
* ``Data.Tuple.Experimental``, for example, is an companion/extension of ``Data.Tuple``; some exports may move from one to the other. Many developers sort their imports alphabetically. Making this a suffix means all ``Data.Tuple``-related imports are next to each other. For example, one might prefer this::
98+
99+
import Control.Applicative
100+
import Control.Applicative.Experimental
101+
import Control.Arrow
102+
import Data.Tuple
103+
import Foreign.C
104+
import Foreign.C.Experimental
105+
106+
to this::
107+
108+
import Control.Applicative
109+
import Control.Arrow
110+
import Experimental.Control.Applicative
111+
import Experimental.Foreign.C
112+
import Data.Tuple
113+
import Foreign.C
114+
115+
This pattern, of a module in ``ghc-experimental`` that is closely related to one in ``base`` seems likely to be common.
116+
117+
* On the other hand, GHC-internal modules are often unrelated to the naming
118+
scheme of ``base``. Here a prefix feels more appropriate. Moreover using a
119+
prefix aligns with current practice: the ``GHC.*`` convention is extensively
120+
used in the GHC-internal modules currently in ``base``, and ``ghc-prim``, as
121+
well as the modules that implement GHC itself.
122+
123+
Proposal 3
124+
-----------
125+
126+
The current ``base`` API exposes many modules starting with ``GHC.*``, so the proposed conventions could only
127+
apply to *new* modules.
128+
129+
* Over time, and only with the agreement and support of the Core Libraries Committee, we may remove some ``GHC.*`` modules
130+
from ``base``, especially ones that are barely used, or are manifestly "internal" (i.e. part of the implementation
131+
of other, more public functions).
132+
Of course there would be a significant deprecation cycle, to allow client libraries to adapt.
133+
134+
Proposal 3 only expresses a direction of travel. We will have to see what the CLC's attitude is,
135+
and what the Haskell community thinks. Anything that disturbs the API of base needs to be considered
136+
rather carefully.
137+
138+
139+
Proposal 4
140+
------------
141+
142+
All of the modules in package ``ghc`` currently start with ``GHC.*`` which
143+
(currently correctly) signals that they are part of GHC's internals.
144+
145+
As part of the GHC API redesign (a HF project in its own right, currently stalled) it would be very helpful
146+
to identify a (multi-module) stable API for package ``ghc``. In that way, users of package ``ghc``
147+
could know whether
148+
they are using a curated, relatively-stable API function, or reaching deep into GHC's guts and using
149+
a random fuction whose name or type, or very existence, might change without warning. Hence:
150+
151+
* The public API of package ``ghc`` (GHC as a library) should have modules whose names clearly distinguish them
152+
from internal modules.
153+
154+
For example, the public API could have modules of form ``GhcAPI.*``, or ``GHC.API.*``, or ``Language.Haskell.GHC.*`` or something else. The specifics are a matter for the future GHC API working group.
155+
156+
157+
158+
Timescale
159+
==========
160+
The first release of GHC with ``ghc-experimental`` and ``ghc-internal`` will be GHC 9.10, which expect to
161+
release in early 2024. It would be good to establish naming conventions for modules well before this date.
162+
163+
Example lifecycle
164+
===================
165+
166+
By way of example, consider the ``HasField`` class, which supports overloaded record fields.
167+
It is currently defined in ``base:GHC.Records``, which is an odd module to have to import.
168+
Moreover there is
169+
more than one GHC proposal that suggest changes to its design (e.g. see `GHC Proposal 158 <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0158-record-set-field.rst>`_); it is not nearly as stable as most of ``base``
170+
171+
If ``ghc-experimental`` had existed we would have put it in ``ghc-experimental:Data.Records.Experimental``.
172+
That would have made it clear that the design of overloaded records still evolving.
173+
Once the design becomes settled and stable, it could move to ``base``, perhaps in a module like ``Data.Records``.
174+
175+
Other similar examples include
176+
177+
* The tuple proposal of `GHC Proposal 475 <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0475-tuple-syntax.rst>`_
178+
* `GHC Proposal 330 (Decorate exceptions with backtrace information) <https://github.com/bgamari/ghc-proposals/blob/stacktraces/proposals/0000-exception-backtraces.rst>`_ proposes significant new additions to the API of exceptions.
179+
180+
Alternatives
181+
==============
182+
* We could dispute Proposal 1: one could imagine deliberately naming modules in ``ghc-experimental`` with the
183+
same module name as their eventual expected (by someone) home in ``base``. The goal would be to reduce impact if and when
184+
the module moves from ``ghc-experimental`` to ``base``. For example, we might add ``Data.Tuple`` to ``ghc-experimental`` containing the new type constructors ``Tuple2``, ``Tuple3`` etc that are proposed in `GHC Proposal 475 <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0475-tuple-syntax.rst>`_. However:
185+
186+
* In the meantime there are two modules both called ``Data.Tuple``. This is bad. Which one does ``import Data.Tuple`` import? (Look at the Cabal file, perhaps?) How can I import both? (Package-qualified imports perhaps.) So it will really only help in the case of a brand-new module, not already in ``base``.
187+
* It loses the explicit cue, in the source code, given by ``import Data.Tuple.Experimental``.
188+

0 commit comments

Comments
 (0)