[Haskell-cafe] An Easy Solution to PVP Bounds and Cabal Hell
olf at aatal-apotheke.de
Thu Apr 2 20:08:10 UTC 2015
I am mostly a consumer of Haskell and have not worked much with the interior of cabal or GHC, but Thomas Tuegel correctly pointed out that with version numbers a package can never safely depend on another package version that was released after itself. The empirical approach of trying builds is probably the most inclusive one.
But let us think why dependencies can break a package. It is because a function was removed from the namespace, conflicting things have been added to the namespace, a data type definition has changed or the modules have been re-structured. In the worst case, none of the above has happened but the semantics of a function has changed without affecting its type. But all other cases can be dealt with: When importing a module, either a smart compiler figures out or the programmer states explicitly which imported functions are expected to be provided by the imported module and what type they have. Thus, the version number of a package is replaced by the collection of classes, types and type signatures its modules export. After all, the version number can be seen as a crude „hash“ of this information. For example, instead of stating
import Data.List (mapAccumL)
on would say
import Data.List (mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y]))
or rather the compiler would fill in this information and save it together with the package as a dependency.
Now when a new version of Data.List comes out, it can be automatically checked whether all functions _used_ by the importing module are still exported and have the same type signature. Modulo semantics, this should be a pretty good estimate of whether a build will fail or succeed.
One could possibly even add QuickCheck properties to the signatures stating that the imported functions are expected to behave in a certain way in the importing module. When installing the new package on a system, all these assertions need to be checked. Isn’t that what configure scripts do prior to executing a makefile?
More information about the Haskell-Cafe