4
votes

I'm pretty new to Haskell, and I think I have a fundamental misunderstanding somewhere. When I'm in GHCi (using the ghci command), I can type import System.Random, and it works. I can then generate random numbers.

Next, I make a file called test.hs that contains nothing but one line: import System.Random. I then call the command ghc test.hs and get the following error message:

test.hs:1:1: error:
    Could not find module ‘System.Random’
    There are files missing in the ‘random-1.1’ package,
    try running 'ghc-pkg check'.
    Use -v to see a list of the files searched for.
  |
1 | import System.Random
  | ^^^^^^^^^^^^^^^^^^^^

However, if I go back to GHCi, I can type :load test.hs. This works, and allows me to generate random numbers.

When I run ghc-pkg check, I get only warnings about missing haddock interface files: https://pastebin.com/6a9f0nYZ. From what I understand, this isn't related to the current issue.

Also, when I run ghc-pkg list, random-1.1 is in the list, so random should be installed.

A couple of questions:

  • Why would GHC and GHCi have access to different imports? Why is the system set up that way? Maybe I just don't understand the relationship between GHC and GHCi.
  • According to the error message, there are "files missing." How can I figure out which files?
  • How can I make it so that I can compile Haskell files that use System.Random?

Edit: Both GHC and GHCi are the same version.

$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 8.6.4
$ ghci --version
The Glorious Glasgow Haskell Compilation System, version 8.6.4

Edit: Both ghc and ghci are in /usr/bin/

$ which ghc
/usr/bin/ghc
$ which ghci
/usr/bin/ghci
1
Are they different versions?Thomas M. DuBuisson
Both are version 8.6.4Finn
What do which ghc and which ghci show? I imagine you may have two copies of haskell installed, one of which is broken.amalloy
@amalloy both are in /usr/bin/. How could I figure out if/where/how I have two copies of Haskell installed?Finn

1 Answers

2
votes

Update: It looks like this is an Arch Linux peculiarity, not a corrupt package. I've updated my answer accordingly.

GHCi loads "dynamic" versions of modules. By default, GHC links with "static" versions of modules. In particular, when you run:

> import System.Random

under GHCi, it tries to access the file Random.dyn_hi to get interface information for the module. In contrast, when you compile a file with that import statement in it, GHC tries to access the file Random.hi.

You can verify this is the issue by running ghc-pkg field random import-dirs and peeking in the resulting directory. There should be a System subdirectory that usually has two files in it: System.hi and System.dyn_hi. If the former is missing, that's your problem.

Now, it looks like you're probably using Arch Linux. As documented on the Arch Haskell wiki page in the section "Problems with linking", the Arch Haskell community packages (including haskell-random) intentionally omit the static versions of interface files and libraries.

There are several of workarounds given there:

  • You can use dynamic linking when compiling with GHC. When using GHC directly, this just means passing the -dynamic flag. For Cabal-based projects, instructions are given on that page for modifying your ~/.cabal/config to use dynamic linking for all projects.
  • You can install the ghc-static and ghc-pristine packages and set up your path and/or Cabal to use the compiler in /usr/share/ghc-pristine/bin/ghc which will maintain its own separate package database that won't interfere with globally installed Haskell community packages, like haskell-random.
  • You can install ghc-static to get static versions of the base libraries and then run cabal install --force-reinstalls somepackage for all the non-base packages you need. Note that the Wiki notes that this can be tedious and complicated, since you have to manually determine all the package dependencies.

Now, it looks like you already had ghc-static installed, or when invoking GHC you would have also gotten an error about missing files in the base package. You ran cabal install --force-reinstalls random, though as @dfeuer notes, it might have been safer to run:

$ cabal install --force-reinstalls random-1.1

to ensure that the same version was reinstalled.

Anyway, this installed an additional copy of random in your user-specific package directory. If you run:

$ ghc-pkg list

you'll see that random-1.1 is listed both under the global database and user database:

/usr/lib/ghc-8.6.4/package.conf.d
    ...
    random-1.1
    ...
/home/xxxx/.ghc/x86_64-linux-8.6.4/package.conf.d
    random-1.1

and if you run:

$ ghc-pkg describe random

you'll see that it lists the two separate installed versions which is why you now get duplicate fields with ghc-pkg field random import-dirs.

There shouldn't be anything wrong with this. Your user database will take precedence over the global database, so your newly installed version of random will be used when you run GHCi or GHC.

Note that, if you change your mind and want to back out this reinstallation (and maybe try one of the other solutions suggested on the Wiki), you should be able to run:

$ ghc-pkg unregister --user random

Technically, this won't actually remove the package (as the compiled version will still be there under ~/.cabal/lib), but it should otherwise put things back the way they were.