tl;dr: Nuke ~/.ghc and then run cabal install --lib (every lib you need)
Edit: Since writing this post, there’s been some movement on the cabal bug, and it seems like there’s soon going to be a fix!
I’m trying to write a simple webserver based on Warp, but I ran into an issue with a hidden package. Here’s my imports in Server.hs:
{-# LANGUAGE OverloadedStrings #-} import Network.Wai (Application, Response, rawPathInfo, responseFile, responseLBS) import Network.HTTP.Types (status200, status404) import Network.Wai.Handler.Warp (run)
And here’s the relevant part of my .cabal file:
executable server main-is: Server.hs build-depends: base >=4.12 && <4.13 , wai , warp default-language: Haskell2010
Note that http-types
is missing, but we’ll come back to that at the end.
I’ll start by saying that I don’t fully understand the difference between cabal and stack, and at the beginning I decided to just use cabal and not worry about stack.
I ran cabal install wai warp
and got the following error:
Resolving dependencies... cabal: Cannot build the executables in the package wai 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. Cannot build the executables in the package warp 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.
It turns out the solution to this is to append --lib
and run cabal install --lib wai warp
. (I wish it would say that in the warning though.)
I ran cabal install wai warp --lib
and tried running Server.hs by pressing command+b in Sublime Text 3, but I ran into this error:
Could not load module ‘Network.HTTP.Types’ It is a member of the hidden package ‘http-types-0.12.3’. You can run ‘:set -package http-types’ to expose it. (Note: this unloads all the modules in the current scope.) Use -v to see a list of the files searched for.
I think what’s happening here is that http-types is installed, but not explicitly. Haskell wants me to definitely say that I want it, so I try running cabal install --lib http-types
.
This, however, runs into a very frustrating error. Apparently the process
library is required at two different versions in two different packages – despite already being happily installed as an indirect dependency:
cabal: Could not resolve dependencies: [__0] trying: base-4.12.0.0/installed-4.1... (user goal) [__1] trying: ghc-8.6.5/installed-8.6... (user goal) [__2] next goal: process (user goal) [__2] rejecting: process-1.6.8.2, process-1.6.8.1, process-1.6.8.0 (constraint from user target requires ==1.6.7.0) [__2] rejecting: process-1.6.7.0 (conflict: ghc => process==1.6.5.0/installed-1.6...) [__2] rejecting: process-1.6.6.0, process-1.6.5.1, process-1.6.5.0/installed-1.6..., process-1.6.5.0, process-1.6.4.0, process-1.6.3.0, process-1.6.2.0, process-1.6.1.0, process-1.6.0.0, process-1.5.0.0, process-1.4.3.0, process-1.4.2.0, process-1.4.1.0, process-1.4.0.0, process-1.3.0.0, process-1.2.3.0, process-1.2.2.0, process-1.2.1.0, process-1.2.0.0, process-1.1.0.2, process-1.1.0.1, process-1.1.0.0, process-1.0.1.5, process-1.0.1.4, process-1.0.1.3, process-1.0.1.2, process-1.0.1.1, process-1.0.0.0 (constraint from user target requires ==1.6.7.0) [__2] fail (backjumping, conflict set: ghc, process) After searching the rest of the dependency tree exhaustively, these were the goals I've had most trouble fulfilling: process, base, ghc
The solution to this is very frustrating, because even rolling back my git repo to the last known good commit didn’t fix it – it’s a global system problem (ironic, for Haskell, which is so demanding of “pureness” in the language). I deleted ~/.ghc
and ran the install again:
rm -rf ~/.ghc && cabal install --lib wai warp http-types
And it worked! My server runs 🙂
The problem is now, I want to build some tests, so I run cabal install --lib hspec
and I run into the same “could not resolve dependencies” as above!
Hm, let’s see if just a rm -rf ~/.ghc && cabal install
will fix it, if I declare hspec
in build-depends
in my .cabal file? I get the following error:
cabal: Path '/Users/erty/.cabal/bin/server' already exists. Use --overwrite-policy=always to overwrite.
So let’s try the suggestion and run --overwrite-policy=always
. Infuriatingly, this build succeeds but when I try to actually run Server.hs (by pressing cmd+b in Sublime Text, perhaps that’s missing a flag or something? I wonder if cabal install builds a binary but fails to install the libraries) it fails to find any of my modules:
Could not find module ‘Network.Wai’ Could not find module ‘Network.HTTP.Types’ Could not find module ‘Network.Wai.Handler.Warp’
Let’s try rm -rf ~/.ghc && cabal install --lib
, since adding --lib
worked before. First, I also added http-types
to my build-depends
in the .cabal file. Nope:
Resolving dependencies... cabal: Cannot build the libraries in the package crossword-hs because it does not contain any libraries. Check the .cabal file for the package and make sure that it properly declares the components that you expect.
But! We were able to get it working by listing all of the dependencies explicitly during the install phase. So let’s try that and run rm -rf ~/.ghc && cabal install --lib wai warp http-types hspec
:
Works! The problem is that I have to remove ~/.ghc manually list out all of my deps every time I want to install something, but at least I can move forward for now.
I also added http-types
to my cabal file, but it didn’t seem to really matter for running in sublime text, as long as I’d installed it via cabal install --lib
.
I would love to hear from any more experienced haskellers out there if I’m not understanding something about cabal. Specifically, coming from node, I feel like cabal install
(or even with --lib
should “just work” and install all of the deps I’ve listed in the .cabal file.
Hopefully this writeup saves someone else time 🙂