
Cabal is just a convenient way of grouping together the denotational /interface/ of a large bunch of modules. The implementations of those modules can be replaced at any time, provided they still meet the interface.
build-depends: package list A list of packages, possibly annotated with versions, needed to build this one, e.g. foo > 1.2, bar. If no version constraint is specified, any version is assumed to be acceptable.
I interpret "needed to build this one" as requirement rather than recommendation. So I interpret build-depends as determining the referent.
"Needed to build" tells me which interfaces must be available at compile-time, no more and no less. I found recently that ghc-pkg (whose input format is essentially Cabal+extras) has a separate "builds" field, which maps the interfaces given in the "build-depends" field to a set of specific implementations. So the referent is (potentially) determined separately from the interface. Your confusion probably arises because there is no really hard separation between interface and implementation in the Haskell'98 source language. As it happens, different compilers blur the boundary between interface and implementation to a greater or lesser extent. But that's a compiler issue, not something intrinsic to either the language or to Cabal. OK, maybe you could complain that the language spec should be more explicit about interfaces, and I might be inclined to agree. (Versions 1.0 and 1.1 actually mentioned interface files, but they were deleted in 1.2, long before the '98 standard.)
Moreover, I think Simon does too. He proposes that we should lift the overlap restriction by having module names map to (cabal-package, module) pairs.
Well, the overlap restriction exists in the language already. If you want to lift it, you really need to change the language. Simon's proposal (which I support) is a hack to permit the restriction to be lifted without changing existing code, by re-interpreting all module imports to have an implicit (disambiguating) prefix. It is just an engineering tradeoff to ensure that huge mounds of legacy code are not broken purely for the sake of some rather rare overlap case. I think, even with the lifting of the overlap restriction, it will still be the base that certain compilers could permit the remapping of (package-version-module) identifiers to implementations. The version uniquely identifies the interface, not necessarily the implementation. Of course, in that situation, it starts to become complicated, because then you will want separate identifiers/versions for different implementations that match a particular (version of the) interface. Regards, Malcolm