Haskell packages not listed in ghc-pkg when installed through Nix - haskell

I have installed GHC through Nix:
$ nix-env -i ghc
Then I have installed the aeson package:
$ nix-env -f "<nixpkgs>" -iA haskellPackages.aeson
And pointed GHC to the Nix package folder:
$ export GHC_PACKAGE_PATH=~/.nix-profile/lib/ghc-8.0.1/package.conf.d/
Which seems to work:
$ ghc-pkg list
/Users/zoul/.nix-profile/lib/ghc-8.0.1/package.conf.d
Cabal-1.24.0.0
array-0.5.1.1
…
But the aeson package is missing from the list of packages above and can’t be loaded. Even though there’s clearly something there:
$ ls /Users/zoul/.nix-profile/lib/ghc-8.0.1/ | grep ^ae
aeson-0.11.2.1
What am I doing wrong?

You cannot install Haskell libraries in Nix that way because the ghc compiler you're using does not search your user's profile for libraries. Consequently, installing a library there has no effect. This topic is explained in great detail in the Nixpkgs user manual. I'm citing the relevant bit from "8.5.2.2. How to install a compiler with libraries":
GHC expects to find all installed libraries inside of its own lib directory. This approach works fine on traditional Unix systems, but it doesn’t work for Nix, because GHC’s store path is immutable once it’s built. We cannot install additional libraries into that location. As a consequence, our copies of GHC don’t know any packages except their own core libraries, like base, containers, Cabal, etc.
We can register additional libraries to GHC, however, using a special build function called ghcWithPackages. That function expects one argument: a function that maps from an attribute set of Haskell packages to a list of packages, which determines the libraries known to that particular version of GHC. For example, the Nix expression ghcWithPackages (pkgs: [pkgs.mtl]) generates a copy of GHC that has the mtl library registered in addition to its normal core packages:
$ nix-shell -p "haskellPackages.ghcWithPackages (pkgs: [pkgs.mtl])"
[nix-shell:~]$ ghc-pkg list mtl
/nix/store/zy79...-ghc-7.10.2/lib/ghc-7.10.2/package.conf.d:
mtl-2.2.1
This function allows users to define their own development environment by means of an override. After adding the following snippet to ~/.nixpkgs/config.nix,
{
packageOverrides = super: let self = super.pkgs; in
{
myHaskellEnv = self.haskell.packages.ghc7102.ghcWithPackages
(haskellPackages: with haskellPackages; [
# libraries
arrows async cgi criterion
# tools
cabal-install haskintex
]);
};
}
it’s possible to install that compiler with nix-env -f "<nixpkgs>" -iA myHaskellEnv.

Related

Why can't the ghc (Haskell) compiler find the module Data.Vector which I have imported? I get the error: Could not find module 'Data.Vector'

vector module has been installed by "cabal install vector"
bash-3.2$ ghc-pkg list -f $HOME/.cabal/store/ghc-9.2.1/package.db
/Users/gcolpitts/.cabal/store/ghc-9.2.1/package.db
primitive-0.7.3.0
vector-0.12.3.1
but the compiler can't find it:
$ ghc prob214ff.hs
[1 of 1] Compiling Main ( prob214ff.hs, prob214ff.o )
prob214ff.hs:14:1: error:
Could not find module ‘Data.Vector’
Perhaps you meant Data.Functor (from base-4.16.0.0)
Use -v (or `:set -v` in ghci) to see a list of the files searched for.
|
14 | import Data.Vector
Thx #n. 1.8e9-where's-my-share !
ghc -package-db $HOME/.cabal/store/ghc-9.2.1/package.db prob214ff.hs
solves my problem although it is a regression from previous versions of ghc which didn't require the use of the -package-db option.
I'd love to use GHC_PACKAGE_PATH but I can't see how to make that work. Sec 5.9.5 of the ghc users guide is confusing. It states "A package database is where the details about installed packages are stored. It is a directory, usually called package.conf.d." i.e. not the package.db file that I gave with -package-db on the command line. But where is the package.conf.db directory with info on the vector package that I installed with cabal?
"ghc-pkg list" references /usr/local/lib/ghc-9.2.1/lib/package.conf.d but the output of the command doesn't list the vector package I installed.
"ghc-pkg list -f $HOME/.cabal/store/ghc-9.2.1/package.db" does list the vector package in it's output but doesn't tell me a package.conf.d directory that knows about the vector package.
This is a bit fiddly with cabal version 2. Installing packages no longer really makes sense (despite the cabal install still existing...). Instead you will probably find it easiest to create a cabal package instead, for example:
$ mkdir my-package
$ cd my-package
$ cabal init
<Edit my-package.cabal and add vector to the build-depends line>
<Put the contents of prob214ff.hs in app/Main.hs instead>
$ cabal run
This will be fixed in 9.2.2, see https://gitlab.haskell.org/ghc/ghc/-/issues/20660#note_391573

How can I tell Cabal where to find alex and happy so that Cabal doesn't try to build them?

I'm developing a Haskell program using Cabal in a nix-shell. I would like to have as many dependencies of the build installed by Nix as possible.
The simple.cabal file seems fairly standard (it was initially produced by stack). The full contents are here: https://pastebin.com/3wd8j0pp The only place alex and happy appear in the .cabal file are in the build-tool-depends sections.
I tried to keep the shell.nix file as simple as possible (but I'm also inexperienced in Nix):
{ pkgs ? import <nixpkgs> {}}:
let
ghc = pkgs.haskellPackages.ghcWithPackages (p:[
p.array
p.base
p.bound
p.containers
p.deriving-compat
p.haskeline
p.logict
p.mtl
p.text
p.unification-fd
p.alex
p.happy
p.BNFC
p.cabal-install
]);
alex = pkgs.haskellPackages.alex;
happy = pkgs.haskellPackages.happy;
in
pkgs.mkShell {
buildInputs = [ ghc pkgs.haskellPackages.alex pkgs.haskellPackages.happy pkgs.pkg-config];
buildTools = [ pkgs.haskellPackages.alex pkgs.haskellPackages.happy];
buildToolDepends = [pkgs.haskellPackages.alex pkgs.haskellPackages.happy];
ALEX="${alex}/bin/alex";
HAPPY="${happy}/bin/happy";
}
I saved environment variables to reference the locations of alex and happy.
Finally, I tried to tell cabal where to find alex and happy by specifying them in the extra-prog-path section of a cabal.project file. However, that didn't work, so I tried hard-coding in their location
packages: simple.cabal
extra-prog-path:
/nix/store/PATH-TO-ALEX/bin/alex
/nix/store/PATH-TO-HAPPY/bin/happy
Finally, on building to enter the nix-shell, nix-shell --pure shell.nix and then cabal build
The cabal tool build finds all the ghc library packages installed with ghcWithPackages correctly -- it requires none of them to be built. However, it seems to not know about alex nor happy. The output looks like this.
In order, the following will be built (use -v for more details):
- alex-3.2.6 (exe:alex) (requires build)
- happy-1.20.0 (exe:happy) (requires build)
I can also confirm that the version of alex and happy in the nix store are alex-3.2.6 and happy-1.20.0.
On the other hand, cabal v1-build does pick up alex and happy as installed. cabal v1-build
Resolving dependencies...
Configuring simple-0.1.0.0...
Preprocessing library for simple-0.1.0.0..
Building library for simple-0.1.0.0..
and the build completes successfully only compiling the source files in the local package.
It seems like one should favor v2-build or new-build. How can I get cabal to know where to find and also to use the alex and happy versions installed by Nix, or alternatively how to tell Nix what to do so that v2-build or new-build can find alex and happy?

Duplicate packages in Haskell environment?

I put this in a file (see bottom) and got the following error when loading it in ghci (i.e. start ghci then :l file):
7:13: error:
• Couldn't match expected type ‘network-uri-2.6.1.0#network-uri-2.6.1.0-7BN1tbB3iHQ2XgvmqLAYph:Network.URI.URI’
with actual type ‘Network.URI.URI’
NB: ‘Network.URI.URI’
is defined in ‘Network.URI’
in package ‘network-uri-2.6.1.0#network-uri-2.6.1.0-80FpvaNUTSDFCPv0sSze40’
‘network-uri-2.6.1.0#network-uri-2.6.1.0-7BN1tbB3iHQ2XgvmqLAYph:Network.URI.URI’
is defined in ‘Network.URI’
in package ‘network-uri-2.6.1.0#network-uri-2.6.1.0-7BN1tbB3iHQ2XgvmqLAYph’
Have I somehow installed two slightly different versions of network-uri, or what is this? How do I resolve it?
I've hardly used cabal but tried cabal install --reinstall network-uri, went fine but problem persists.
File contents:
import Network.HTTP
import Network.URI (parseURI)
import Data.Maybe (fromJust)
myRequestURL = "http://www.virginia.edu/cgi-local/ldapweb"
myRequest :: String -> Request_String
myRequest query = Request {
rqURI = fromJust $ parseURI myRequestURL
, rqMethod = POST
, rqHeaders = [ mkHeader HdrContentType "text/html"
, mkHeader HdrContentLength $ show $ length body ]
, rqBody = body
}
where body = "whitepages=" ++ query
main :: IO ()
main = do
response <- simpleHTTP $ myRequest "poon"
putStrLn ""
EDIT Re-installed haskell-platform. After this, ghc-pkg list reports all packages to be under (?) /usr/lib/ghc/package.conf.d, and the program I tried to copy loads just fine.
EDIT 2 After running cabal install some-pkg, ghc-pkg list reports that the newly installed stuff is in another directory. Indeed, ~/.cabal/config specifies install dirs for user, as well as install dirs for global. How is all this supposed to be managed properly?
GHC understands the concept of package databases. Cabal manages multiple package databases. There's a system package database, and a user package database. When you compile something with Cabal V1, it uses the union of these package databases. This is a bit of a time bomb, because, as you see, GHC does not like it when you have multiple of the same package. When you issued cabal install network-uri, cabal decided to install one copy of that package into your user database, though you already had one in the system database. When you tried to use ghc, it picked up on the two copies and got confused. Because cabal does not support removing packages, your Haskell installation was pretty much borked, and you reinstalled. I believe you could have done a more conservative rm ~/.ghc, or, had you been really adventurous, used the low-level ghc-pkg command to edit the package database.
Now that you've reinstalled the Platform, I would heavily recommend never using cabal install again. It's old, it's broken, cabal itself tells you not to use it. If you're using the Platform, I think it has stack in it, which is a different build manager, based on Cabal, which is not prone to this kind of breakage. Or, you can just stick to the V2 series of cabal commands, which is what I prefer.
Cabal V2 does not directly support your usecase, where you install a package globally and compile a program against it. This is because doing so is fundamentally broken: global package databases really just don't work for GHC. What Cabal V2 does is install packages into your home directory, ~/.cabal/store. You then have to explicitly tell it which packages you want, and it will construct a package database that contains each required package, without any wonkiness. You can get a REPL with a certain set of packages by issuing (this will take you to a temporary directory; you may need to :cd yourself back.)
cabal v2-repl -b network-uri -b package2 -b etc
If you want to actually compile files with ghc with a set packages, you have to actually define a package with a .cabal file. Here's a stub .cabal file:
name: temporary-pkg
version: 0.0.0.0
build-type: Simple
cabal-version: >=2.0
executable main -- if there is no Main, say "library" instead of "executable <name>"
default-language: Haskell2010
main-is: Main.hs -- only valid in executable stanzas
hs-source-dirs: src -- source files go here
build-depends: base, network-uri, package2, etc -- packages go here
Create and enter a directory, place that in temporary-pkg.cabal, place your sources in src/, and you can issue stuff like cabal v2-build and cabal v2-repl and cabal v2-exec main, etc. cabal will go off and install dependencies from Hackage into ~/.cabal/store as needed. cabal v2-install is therefore not that useful here. In general, v2-installing libraries is unnecessary, but v2-installing packages with executables is useful. Again, for hygiene reasons, you have to list all the packages you are importing from, but you don't need to list their dependencies or anything insane like that.
Cabal V2 still doesn't support uninstalling packages, though the point is that should not be necessary. However, if you find ~/.cabal/store getting too large for your liking, you can just nuke it, and should be built back up as packages are requested.

Acid-State example compiled error. No No instance for (Control.Monad.Reader.Class.MonadReader FailureDb (Query FailureDb))

I was trying acid example but compile error.
The error message says no instance No instance for MonadState, No instance for MonadReader.
This article says it is due to two different mtl versions installed.
And I am using nix-shell in nixos:
ghc-pkg list | grep acid
acid-state-0.14.3
ghc-pkg list | grep mtl
mtl-2.2.1
mtl-2.2.2
However, if I don't use acid-state package when I enter nix-shell, I got:
ghc-pkg list | grep mtl
mtl-2.2.2
That probably means acid-state is using different mtl version than Control.Monad.Reader.
But acid-state's stack.yaml in github is lts-11.15, which has mtl-2.2.2.
So what should I do to make it work?
Stack and Cabal-install have similar problems when dealing with GHC's package dbs, but these problems can be avoided:
Stack
When I use Stack, I don't run it in a nix-shell, so that the nix-shell can't add packages to the wrapped GHC command that Stack will then consider to be system packages ('global' in Cabal terminology). I am not sure whether this is the only valid approach though.
Cabal-install only
When calling Cabal in a nix-shell, you should add these flags to prevent GHC from looking at the wrong package db: cabal configure --package-db=clear --package-db=global. The GHC wrapper will make the Nix-managed dependencies appear in the 'global' package db.

GHC can not find installed module

My haskell installation can not find bytestring module installed by operating system
$ ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> :m +Data.ByteString.Lazy
<no location info>:
Could not find module `Data.ByteString.Lazy'
It is not a module in the current program, or in any known package.
But I have installed this module using yum:
$ rpm -ql ghc-bytestring
/usr/lib64/ghc-7.6.3/bytestring-0.10.0.2
/usr/lib64/ghc-7.6.3/bytestring-0.10.0.2/libHSbytestring-0.10.0.2-ghc7.6.3.so
/usr/share/doc/ghc-bytestring
/usr/share/doc/ghc-bytestring/LICENSE
What is wrong?
If this is happening, you should be able to figure out more via ghc-pkg list. This could happen, for example, if the binary package provided by your software repository was broken; ghc-pkg list would report that. In general, either GHC is not looking for packages in /usr/lib64/ghc-7.6.3/ or else that directory has a package.cache which was not updated to reflect the new package.
One thing that could cause GHC to look in the wrong place is if there are multiple GHCs on the machine: for example if which ghc reveals /usr/local/bin/ghc then you probably compiled GHC from source at some point and its packages are occupying some /usr/local/lib/ghc-7.6.3/package.conf.d/ folder, while your repository has installed /usr/bin/ghc which is looking in the folder you want.
Anyway, fixes: if the package.cache file exists and has a valid entry for the file, then you can run ghc -package-conf /path/to/package.cache ... to add those packages to your executable. If you have further problems, ghc -v ... is a great resource for debugging "which version of that package is being used here?" types of problems.
If the package.cache file does not exist then you've got a bigger problem, and probably the easiest way to move forward is to look for a directory under /home which appears on ghc-pkg list. Install the required package to that directory and GHC should pick up on it even though it doesn't understand these bigger contexts. You could also start working with a cabal sandbox of local packages to your project.
Situation here is similiar to C++ you have libraries used during dynamic linking stage and header used for compilation. In Fedora packages like ghc-bytestring are only libraries without headers. To install headers I had to install ghc-bytestring-devel package.
An example on Fedora 24:
server.hs:7:8:
Could not find module ‘Data.Text’
Perhaps you meant Data.Set (from containers-0.5.5.1)
Locations searched:
Data/Text.hs
Data/Text.lhs
So change to user root, then:
What packages are there?
# dnf search ghc|grep text
ghc-text.x86_64 : An efficient packed Unicode text type
ghc-boxes.x86_64 : 2D text pretty-printing library
ghc-pango.x86_64 : Binding to the Pango text rendering engine
ghc-css-text.x86_64 : CSS parser and renderer
ghc-hgettext.x86_64 : Haskell binding to libintl
ghc-attoparsec.x86_64 : Fast combinator parsing for bytestrings and text
ghc-text-devel.x86_64 : Haskell text library development files
ghc-blaze-textual.x86_64 : Fast rendering of common datatypes
ghc-css-text-devel.x86_64 : Haskell css-text library development files
ghc-hgettext-devel.x86_64 : Haskell hgettext library development files
ghc-blaze-textual-devel.x86_64 : Haskell blaze-textual library development files
So what's installed?
# rpm --query ghc-text
ghc-text-1.1.1.3-3.fc24.x86_64
# rpm --query ghc-text-devel
package ghc-text-devel is not installed
So let's install the devel package.
# dnf install ghc-text-devel
Installed:
ghc-text-devel.x86_64 1.1.1.3-3.fc24
...and compilation succeeds after that.

Resources