What to do if libraries require a different version of `base`? - haskell

I'm trying to install packages which require a different version of base than the one I have installed (I have 4.6.0.0, they require < 4.6). How can I install these on my system?
Edit: These packages actually require older packages in order to build, not just as a .cabal constraint.

Since you can't reinstall base, the only way to get these packages installed before they are updated is to grab the source,
cabal unpack foo
and then edit foo.cabal, changing the upper bound for base there, bump the package version (append a .1) so that when installing other packages cabal doesn't think it is broken, since the .cabal file it knows (from the package index) says it requires a different version of base, and
cabal install
from the directory you unpacked to.
Since there were a few significant changes in base-4.6; the Eq and Show superclasses have been removed from Num, and Bits no longer has Num as a superclass, it may be necessary to fix the code by adding Eq, Show or Num to the constraints of some functions to make the packages compile.
That's inconvenient, but the price for being up-to-date yourself with the newest GHC version for a few weeks.

If you just want one of your programs to depend on these packages, you can use cabal-dev as a drop-in replacement for cabal. The former installs local copies of packages in a cabal-dev path in the current directory. To install it, just run:
cabal install cabal-dev
For portability, you may add something like this to a makefile:
CABAL ?= cabal
build :
$(CABAL) build --builddir=$(BUILD_PATH)
Then in your Bash settings:
CABAL=cabal-dev
export CABAL

If a package isn't compatible with the base you currently have (i.e. just changing the constraint is insufficient), your only options are to port the package yourself or use an older ghc that provides the correct version of base.
You might want to check with the package maintainer first though. A development branch may already support what you need, and they just need a little prodding to release it.

Related

How to install an library in Haskell?

I try to use
Control.Monad.Extra.andM
import Control.Monad.Extra (andM)
but has an error:
Could not find module ‘Control.Monad.Extra’
Perhaps you meant
Control.Monad.Catch (needs flag -package-key exceptions-0.10.4)
Control.Monad.Error (needs flag -package-key mtl-2.2.2)
Control.Monad.Except (needs flag -package-key mtl-2.2.2)not found
This error does not make sense.
According to
https://cabal.readthedocs.io/en/3.6/installing-packages.html#installing-packages-from-hackage
3.2.1. Installing packages from Hackage
The cabal tool also can download, configure, build and install a Hackage package and all of its dependencies in a single step. To do this, run:
$ cabal install [PACKAGE...]
To browse the list of available packages, visit the Hackage web site.
Which says "in a single step", but in my experience this is too complicated and actually I have no idea how to install Control.Monad.Extra .
Usually, when a Haskeller want to install a specific library/package like this, how do you do this? There's no adequate documentations, it seems.
How to install an library in Haskell?
You don't. You should just depend on them, and then let Cabal worry about any installations that may need to be done. I.e., as you wrote
Go to the Hackage page and study which exact library to be used.
*.cabal file -> build-depends: extra >=1.7.10
This is the crucial step. Your own Cabal file is the way to both specify what libraries are needed right now, as well as ensuring that everything will still work in the future. This file needs to specify both the packages you require, as well as the modules you're defining yourself.
Probably you don't actually need >=1.7.10, but it can't hurt much to be specific there. Standard practice is to add both lower and upper bounds on the x.y level, i.e. you'd use extra >=1.7 && <1.8, and then push the upper boundary as new versions come out. Arguably this is a bit overcautious; if you only use some simple tools from a package that is unlikely to have breaking changes in the future then it may be less trouble to just leave the upper boundary out.
$ cabal install extra
You've already specified that extra is needed for your project, no need to state that again. Instead, simply build your own project now.$ cabal buildor, to get a GHCi prompt with your modules,$ cabal replor, if you have an executable with a main that you wish to execute$ cabal runor if you want to install that executable (and only then)$ cabal installCabal will then automatically figure out that extra-1.7.10 should be installed first.
(In old Cabal it would still have been necessary to run cabal install --dependencies-only first.)
Ok Self-Answered. Comment me if the information is wrong.
1. Go to the Hackage page and study which exact library to be used.
In this case, it seems extra-1.7.10.
2. *.cabal file -> build-depends: extra >=1.7.10 (among other libs)
3. $ cabal install extra
Error:
cabal: Cannot build the executables in the package extra because it does not contain any executables. Check the .cabal file for the package and make sure that it properly declares the components that you expect.
Well, I did for sure.
4. cabal install extra --lib
Finally works, but the documentation never said this.
Am I correct?
`
Is this the only method? or any other smarter way?

Is there a recommended way to update version bounds on cabal packages?

With the release of GHC 7.10 and the accompanying version bump on the base package I found myself in the situation that I needed to fix my library dependencies.
For the moment I have run cabal install --allow-newer which found a set of working versions and installed fine.
Now I am in the process of manually searching through the installed libraries and updating the cabal files version bounds by hand.
Is there an easier/automatic way to do this?
I regularly use packdeps to check on my dependencies and bump any that are too restrictive. As well as the website, there's a hackage package so you can run it locally.
Once I bump a dependency, e.g. by bumping foo < 1.5 to foo < 1.6, I build and test locally using the --constraint 'foo>=1.5' argument to cabal, to check that the new version does indeed work.
You might like the tool cabal-bounds.

Stackage inclusive or exclusive usage

I'm attempting to start a new project using the Snap web framework. I used snap init to get my basic skeleton working. I also put http://www.stackage.org/lts/cabal.config next to my .cabal file. I didn't uncomment the line to use Stackage exclusively. So I tried to build and it failed and couldn't find the version of lens required by my .cabal file. The cabal.config file from Stackage specifies a version of lens that is not the same as the one in my .cabal file. So I deleted every constraint from my package list and did the usual cabal install --only-dep -j8 --enable-test and it worked!
However, I have always been told that package versions should be constrained. So when working with Stackage is it okay to leave package versions unconstrained? Should I downgrade my packages to the ones available in Stackage instead?
As far as I understand a cabal.config file specifies a set of dependencies with the specific versions that satisfy dependencies, so how does Stackage work? Is it just a subset of packages from Hackage that are proven to be compatible? Do they host their own packages or rely on Hackage for downloads?
Thanks in advance :)
Both options are available. The default option is what you did, and still goes to hackage to get the packages. You just added a filter to your cabal that prevents you from using any version of a package included in Stackage that was not tested to work together with all of the other packages.
The other option is to simply point your cabal repo to a Stackage url, and then you will download packages directly from the Stackage server. That server will only serve packages that are known to work together, so there is no need for additional constraints in your cabal file. I actually prefer this way of working.
In both cases, if you have additional constraints in your cabal file that are incompatible with the Stackage restrictions, your build will fail. If you use the first option, you will get dependency conflicts. When using the second option, the Stackage server will simply report that it does not have that specific package/version.

How can I resolve zlib-enum, zlib-binding, zlib-conduit conflict when installing Yesod

I am trying to install my Yesod web app on another machine.
I have it installed fine on my current machine and can cabal install it on there without any problems.
I seem to run into trouble with it on the other machine though (which is a fresh Ubuntu VM - e.g., no cabal packages where installed on it prior.
Note that I changed nothing about my setup (e.g. cabal files are exactly the same).
This is the error I keep getting:
cabal: cannot configure zlib-enum-0.2.2. It requires zlib-bindings ==0.1.*
For the dependency on zlib-bindings ==0.1.* there are these packages:
zlib-bindings-0.1.0 and zlib-bindings-0.1.0.1. However none of them are available.
zlib-bindings-0.1.0 was excluded because zlib-conduit-0.2.0.1 requires zlib-bindings >=0.0.3 && <0.1
zlib-bindings-0.1.0 was excluded because zlib-bindings-0.0.3.2 was selected instead
zlib-bindings-0.1.0 was excluded because of the top level dependency zlib-bindings ==0.0.3.2
zlib-bindings-0.1.0.1 was excluded because zlib-conduit-0.2.0.1 requires zlib-bindings >=0.0.3 && <0.1
zlib-bindings-0.1.0.1 was excluded because zlib-bindings-0.0.3.2 was selected instead
zlib-bindings-0.1.0.1 was excluded because of the top level dependency zlib-bindings ==0.0.3.2
I have tried all kind of ways to resolve this, but keep running into this same problem, no matter what path I take.
My guess is, that theses packages' versions are conflicting at this point.
How can I resolve this until it gets fixed?
This is a prime example of cabal dependency hell. Theoretically, the fault lies with zlib-enum, since it should have had a major version bump to reflect the major version bump with zlib-bindings. But really, the problem is cabal's dependency analyzer. The new one will hopefully be ready soon.
In the meanwhile, depending on zlib-enum <= 0.2.1 should work.
Also, #ehird's answer should be helpful too, though it may not entirely solve the problem.
You might want to try installing the new Yesod Platform (Hackage page):
cabal install yesod-platform
It's a metapackage that depends on specific versions of Yesod and all its dependencies, designed to avoid versioning conflicts like this.
You could also try the in-development version of cabal-install, which has the modular dependency solver Michael mentioned. If you darcs get --lazy http://darcs.haskell.org/cabal/, you should be able to run bootstrap.sh in cabal/cabal-install to install it (but you should probably wipe ~/.cabal and ~/.ghc first).1 You still have to explicitly request the modular solver by passing --solver=modular to cabal, though.
Note that, even though it's a development version, it's actually pretty stable; lots of people on GHC 7.4.1 (including me) use it, since the version on Hackage doesn't compile. I haven't had any issues so far.
1 This is for Linux; I think the relevant directory is ~/Library/Haskell on OS X. I have no idea what to do on Windows, especially since the shell script won't run there.

Using the --reinstall flag with cabal-dev

I'm working on the wxHaskell library, and wishing to keep my development work separate from the stable wxHaskell from hackage I'm using cabal-dev in the following manner:
I obtained the source for wxHaskell from darcs;
Because wxHaskell is comprised of three components I used cabal-dev add-source to add each one (wx, wxcore, wxdirect);
I was then able to install into a sandbox local package library by doing cabal-dev install wx, as expected, the dependencies were detected and everything built and installed.
Finally I successfully ran my test code by using ghc -package-conf to specify the location of the sandboxed package database.
The problem comes when I make modifications to the wxHaskell source. In order to build and install the updated code I have to use cabal-dev install --reinstall, which makes sense as I don't increment the version number; the build takes place and I see "Installing library in..." and "Registering..." but the changes I've made in the code aren't present in the recompiled sandbox library.
The work around I have at the moment is to delete the cabal-dev library and repeat the process every time I want to rebuild.
UPDATE: cabal-install >= 1.18 has support for sandboxes, and will be better maintained than cabal-dev going forward. Cabal-install also has better support for using add-source with sandboxes. Here's a description of the new sandboxing features in cabal-install: http://coldwa.st/e/blog/2013-07-30-Cabal-sandbox.html
Old answer:
As you found, 'add-source' is not meant for use with actively changing projects. I'm not sure that there is a good solution there either - it's difficult to track the location of an add-source'd project (there is no existing infrastructure for that, at least), and I'm not sure that's always the right thing.
Another workflow may serve you better - just use cabal-dev install, pointing to the sandbox you wish to use for future development. Recent versions of the cabal toolchain (by which I mean Cabal, cabal-install and cabal-dev) allow for this sort of thing:
$ ls
wx wxcore wxdirect
$ cabal-dev install --sandbox=<path-to-some-sandbox> ./wx ./wxcore ./wxdirect
...
(Note: I have not tested this with WX - kinks may arise that I'm unaware of!)
Assuming everything goes as expected, that will install the three packages from the local sub directories into the specified sandbox. Updating the source just means re-issuing a cabal-dev install command for the project that changed.
Keep in mind that you must either issue the repeated cabal-dev install commands in the correct order on your own, or you must use the batch command above and update version numbers accordingly.
I make no claims about this being ideal ;) but I think it's better than deleting the sandbox each time.
After some investigation I can confirm that this is a result of my misunderstanding regarding the usage of add-source, as detailed in "Using a sandbox-local Hackage" section of the README, which is given here (the strong was added by myself and indicates the reason for my misunderstanding):
Cabal-dev also allows you to use un-released packages as though they
were on hackage with cabal-dev add-source.
For example, the linux-ptrace and posix-waitpid packages were only
recently uploaded to hackage. Previously, cabal-dev was used to build
applications that depended on these two packages:
$ ls
linux-ptrace/ myProject/ posix-waitpid/
$ cd myProject
$ cabal-dev add-source ../linux-ptrace ../posix-waitpid
$ cabal-dev install
Note that cabal-dev add-source accepts a list of source locations.
Be careful, however, because packages that have been added are not
tied to their original source locations any more. Changes to the
linux-ptrace source in the above example will not be used by
myProject unless the user issues cabal-dev add-source with the
path to the linux-ptrace source again. This is similar to the
cabal install step you may do now to enable a project to make use of
changes to a dependency.

Resources