
Duncan Coutts wrote:
In the initial discussions on a common architecture for building applications and libraries one of the goals was to reduce or eliminate untracked dependencies. The aim being that you could reliably deploy a package from one machine to another.
Sorry for jumping in so late but here are my two cents anyway. IMO, a package is absolutely the wrong thing to depend on. Essentially, a package is an implementation of an interface and depending on implementations is a bad thing. Code should only depend on interfaces which are completely independent entities. I suspect that a lot of the problems with packages occur because the current system doesn't follow this simple principle. It would be nice if Cabal had an explicit concept of interfaces, with the idea that code depends on them and packages implement them. In the simplest case, an interface is just a name. Ideally, it would be a combination of type signatures, Quickcheck properties, proof obligations etc. The important thing is that it has an explicit definition which is completely independent of any concrete implementation and which never changes. Something like this would immediately solve a lot of problems. Several packages could implement the same interface and we could pick which one we want when building stuff. We could have much more fine-grained dependencies (if all I need is an AVL tree, I don't want to depend on the entire containers package, but rather just on the AVL part of it). One package could implement several versions of an interface to ensure compatibility with old code (I could imagine module names like AVL_1.Data.AVLTree, AVL_2.Data.AVLTree etc., where AVL_1 and AVL_2 are interface names; Cabal could then map the right module to Data.AVLTree when building). If interface definitions include something like Quickcheck properties, we would have at least some assurance that a package actually does implement its interfaces. Moreover, this would also make the properties themselves reusable. Note that I don't propose that we automatically extract interfaces from code. In fact, I think that would be precisely the wrong way to go. An interface is not a by-product of implementing a package. It should be defined explicitly. In general, I don't think that existing package management systems do a very good job of specifying dependencies. They sort of work for distributing software but do they really work for versioning libraries? In any case, we ought to have something better for Haskell where we (hopefully) have somewhat different standards when it comes to correctness and ease of use. It might be more worthwhile to look at systems such as Corba, Microsoft's OLE or whatever that's called nowadays, Java's equivalent, whatever that is and, of course, ML's modules. None of these is quite right for what we want but IMO they are much closer to our problem domain than something like RPM. Roman