为什么GHCi了解GHC不了解的进口商品?

时间:2019-04-20 15:04:37

标签: haskell ghc ghci

我对Haskell来说还很陌生,我认为我在某个地方有一个基本的误解。当我处于GHCi中时(使用ghci命令),我可以键入import System.Random,它可以工作。然后,我可以生成随机数。

接下来,我制作一个名为test.hs的文件,其中仅包含一行:import System.Random。然后,我调用命令ghc test.hs并收到以下错误消息:

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
  | ^^^^^^^^^^^^^^^^^^^^

但是,如果我返回到GHCi,则可以键入:load test.hs。这有效,并且允许我生成随机数。

运行ghc-pkg check时,只会收到有关缺少haddock界面文件的警告:https://pastebin.com/6a9f0nYZ。据我了解,这与当前问题无关。

此外,当我运行ghc-pkg list时,random-1.1在列表中,因此应该安装random

几个问题:

  • 为什么GHC和GHCi可以使用不同的进口产品?为什么以这种方式设置系统?也许我只是不了解GHC和GHCi之间的关系。
  • 根据错误消息,存在“文件丢失”。如何找出哪些文件?
  • 如何做到这一点,以便可以编译使用System.Random的Haskell文件?

编辑:GHC和GHCi都是相同的版本。

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

编辑:ghcghci都在 / usr / bin /

$ which ghc
/usr/bin/ghc
$ which ghci
/usr/bin/ghci

1 个答案:

答案 0 :(得分:2)

更新:看起来这是Arch Linux的独特之处,而不是损坏的软件包。我已经相应更新了答案。

GHCi加载模块的“动态”版本。默认情况下,GHC与模块的“静态”版本链接。特别是在您运行时:

> import System.Random

在GHCi下,它尝试访问文件Random.dyn_hi以获取模块的接口信息。相反,当您编译其中包含该import语句的文件时,GHC会尝试访问文件Random.hi

您可以通过运行ghc-pkg field random import-dirs并查看结果目录来验证这是问题所在。应该有一个System子目录,该子目录中通常包含两个文件:System.hiSystem.dyn_hi。如果缺少前者,那就是您的问题。

现在,您似乎正在使用Arch Linux。如Arch“ Haskell wiki page”部分“链接问题”中所述,Arch Haskell社区软件包(包括haskell-random)有意省略了接口文件和库的静态版本。

有几种解决方法:

  • 使用GHC编译时,可以使用动态链接。直接使用GHC时,这仅意味着传递-dynamic标志。对于基于Cabal的项目,该页面上提供了有关修改~/.cabal/config以对所有项目使用动态链接的说明。
  • 您可以安装ghc-staticghc-pristine软件包,并设置路径和/或Cabal以在/usr/share/ghc-pristine/bin/ghc中使用编译器,这将维护自己的独立软件包数据库,而不会干扰全局安装的Haskell社区软件包,例如haskell-random
  • 您可以安装ghc-static以获得基本库的静态版本,然后对所需的所有非基本包运行cabal install --force-reinstalls somepackage。请注意,Wiki指出这可能很繁琐且复杂,因为您必须手动确定所有软件包的依赖关系。

现在,看来您已经安装了ghc-static,或者在调用GHC时也会 收到有关base软件包中丢失文件的错误。您运行了cabal install --force-reinstalls random,但正如@dfeuer所指出的那样,它可能更安全地运行:

$ cabal install --force-reinstalls random-1.1

以确保重新安装了相同的版本。

无论如何,这会在您的用户特定的软件包目录中安装random的其他副本。如果您运行:

$ ghc-pkg list

您会看到random-1.1同时在全局数据库和用户数据库下列出:

/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

,如果您运行:

$ ghc-pkg describe random

您会看到它列出了两个单独的安装版本,这就是为什么现在使用ghc-pkg field random import-dirs获得重复字段的原因。

这应该没有什么问题。您的用户数据库将优先于全局数据库,因此在运行GHCi或GHC时将使用新安装的random版本。

请注意,如果您改变主意并希望退出此重新安装(并尝试使用Wiki建议的其他解决方案之一),则应该能够运行:

$ ghc-pkg unregister --user random

从技术上讲,这实际上不会删除该软件包(因为编译后的版本仍将位于~/.cabal/lib下),但应以其他方式将其恢复原状。