Being able to install a tarball is a great first step and would provide a mechanism for taking care of some of the use cases.
In terms of specific user interaction plans for installing from a repo, I would point again to ruby's Bundler as a starting point. Basically instead of putting in a version number constraint one can put in a git url. That url points to a repo with a gemspec (.cabal file) which has the version number. It is important to note that Bundler operates and a project-focused manner. Bundler also creates a file 'Gemfile.lock' which lists every package being used for the project and its exact version. This helps when working in a team or deploying- by checking in this file one can ensure that everyone else (and the production server) is using the *exact* same versions of packages. For library development it is not recommended to check in the lock file. Changing the Gemfile (cabal file) and installing (cabal configure) will update the lock file.
This functionality is similar to the tool capri in some ways, but instead of having a project private package set it just has a lockfile that specifies exact versions. I think haskell may require a project private repo because it compiles packages instead of interpreting them. For a project private package set in Ruby there is a tool called RVM which has a feature called 'gemsets'. The main purpose of RVM though, is actually to be able to easily switch between multiple versions of Ruby (and it does this amazingly well by operating at the shell level).
I am rambling now, but the end user interaction is essentially just editing the Cabal file with the proper git url and re-compiling. The releaser does not have to do anything either- they don't even have to change the version number in the cabal file. Ruby Gems and Bundler use the git hash of the repo as the version number. However, Bundler still knows the package version number for dependency resolution.