base library and GHC 6.12
marlowsd at gmail.com
Mon Jun 29 08:22:21 EDT 2009
On 27/06/2009 02:07, Henning Thielemann wrote:
> Ian Lynagh schrieb:
>> Option 1
>> In order to solve the version number issue, we could simply state that
>> "base follows the PvP, but only for shared module hierarchies". However,
>> it would be impossible for packages which /do/ need GHC.* modules to
>> give accurately versioned dependencies, and it wouldn't solve the other
>> issue at all.
>> Option 2
>> Another possible solution would be to rename the base package to
>> base-internals, and to make base only re-export the "public" modules.
>> This would require either renaming each module M to Internal.M, or for
>> every implementation to support something like GHC's PackageImports
>> Option 3
>> The other alternative is to try to split base into two parts: The shared
>> "public" modules, and the internal GHC.* modules. Then GHC would have
>> ghc-base, hugs would have hugs-base, etc, and there would be a common
>> base package built on top of the appropriate impl-base.
> This sounds most sensible to me. I would also like to see
> System.IO.Unsafe in a separate package. This would simplify running of
> untrusted code.
I think the point that hasn't been made clearly so far is this: it's
simply not possible to get a clean split between the compiler-specific
portions and the portable portions of the base package.
Imagine trying to do this. Firstly, you have to establish a clear API
boundary between the portable code and the compiler-specific
implementations of various primitives. For instance, the definition of
the Prelude in the Haskell 98 report refers to things like
"primPlusInt". Now, move the implementations of the compiler-specific
primitives into their own package, leaving the portable code behind.
In theory this sounds fine, but in practice the compiler-specific code
wants to depend on portable bits. A basic example is list operations
like 'map'; almost certainly you'll want this in the compiler-specific
package. There are many more; for example the FFI is needed pretty
early on, but most of the FFI libraries are portable.
When you start separating dependencies it all gets pretty tedious, and
what's more you're never sure whether the dependencies might change in
the future, requiring yet more code to move across the boundary in one
direction or another. And you'll invariably end up with a bunch of
portable code on the wrong side of the boundary. There's no good way to
I argue that separating the implementations like this (a) is a time sink
and (b) makes the code harder, not easier, to work with. What's really
important is that we can expose a portable API. The implementation can
stay all in one package where it is convenient, letting us interleave
portable and non-portable code in the dependency graph arbitrarily.
Obviously we should continue to make every attempt to clearly separate
portable from non-portable code using the module system, within the base
So, unless it isn't clear, I claim option (2) is the way forward.
Now, there are a couple of problems with it:
- firstly, compilers other than GHC don't support re-exporting modules
- Haddock doesn't support it properly either, unless Isaac Dupree's
SoC project comes to fruition in time for the release. This
would be a show-stopper.
More information about the Libraries