为什么 GHCi 理解 GHC 不理解的导入?
Why does GHCi understand imports that GHC doesn't?
我是 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
时,我只收到有关缺少黑线鳕接口文件的警告:https://pastebin.com/6a9f0nYZ。据我了解,这与当前问题无关。
此外,当我运行 ghc-pkg list
时,random-1.1
在列表中,所以应该安装random
。
几个问题:
- 为什么 GHC 和 GHCi 可以访问不同的导入?为什么系统会这样设置?可能我只是不明白GHC和GHCi的关系
- 根据报错信息,有"files missing."如何找出是哪些文件?
- 我怎样才能编译 Haskell 个使用
System.Random
的文件?
编辑: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
编辑:ghc
和 ghci
都在 /usr/bin/
$ which ghc
/usr/bin/ghc
$ which ghci
/usr/bin/ghci
更新: 看起来这是 Arch Linux 的特性,而不是损坏的包。我已经相应地更新了我的答案。
GHCi 加载 "dynamic" 版本的模块。默认情况下,GHC 链接 "static" 版本的模块。特别是,当您 运行:
> import System.Random
在 GHCi 下,它会尝试访问文件 Random.dyn_hi
以获取模块的接口信息。相反,当您编译一个包含该 import 语句的文件时,GHC 会尝试访问该文件 Random.hi
.
您可以通过 运行ning ghc-pkg field random import-dirs
并查看生成的目录来验证这是问题所在。应该有一个 System
子目录,里面通常有两个文件:System.hi
和 System.dyn_hi
。如果缺少前者,那是你的问题。
现在,您可能正在使用 Arch Linux。正如 "Problems with linking" 部分中关于 Arch Haskell wiki page 的文档所述,Arch Haskell 社区包(包括 haskell-random
)有意省略了接口文件和库的静态版本。
那里给出了几种解决方法:
- 您可以在使用 GHC 编译时使用动态链接。直接使用 GHC 时,这仅意味着传递
-dynamic
标志。对于基于 Cabal 的项目,该页面上给出了修改 ~/.cabal/config
以对所有项目使用动态链接的说明。
- 您可以安装
ghc-static
和 ghc-pristine
包并设置路径 and/or Cabal 以使用 /usr/share/ghc-pristine/bin/ghc
中的编译器,它将维护自己独立的包数据库不会干扰全局安装的 Haskell 社区包,例如 haskell-random
.
- 您可以安装
ghc-static
以获得基础库的静态版本,然后 运行 cabal install --force-reinstalls somepackage
获取您需要的所有非基础包。请注意,Wiki 指出这可能既乏味又复杂,因为您必须手动确定所有包依赖项。
现在,看起来您已经安装了 ghc-static
,或者在调用 GHC 时您会 也 收到有关 [=32= 中丢失文件的错误] 包裹。你 运行 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
下),但它应该会恢复原样。
我是 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
时,我只收到有关缺少黑线鳕接口文件的警告:https://pastebin.com/6a9f0nYZ。据我了解,这与当前问题无关。
此外,当我运行 ghc-pkg list
时,random-1.1
在列表中,所以应该安装random
。
几个问题:
- 为什么 GHC 和 GHCi 可以访问不同的导入?为什么系统会这样设置?可能我只是不明白GHC和GHCi的关系
- 根据报错信息,有"files missing."如何找出是哪些文件?
- 我怎样才能编译 Haskell 个使用
System.Random
的文件?
编辑: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
编辑:ghc
和 ghci
都在 /usr/bin/
$ which ghc
/usr/bin/ghc
$ which ghci
/usr/bin/ghci
更新: 看起来这是 Arch Linux 的特性,而不是损坏的包。我已经相应地更新了我的答案。
GHCi 加载 "dynamic" 版本的模块。默认情况下,GHC 链接 "static" 版本的模块。特别是,当您 运行:
> import System.Random
在 GHCi 下,它会尝试访问文件 Random.dyn_hi
以获取模块的接口信息。相反,当您编译一个包含该 import 语句的文件时,GHC 会尝试访问该文件 Random.hi
.
您可以通过 运行ning ghc-pkg field random import-dirs
并查看生成的目录来验证这是问题所在。应该有一个 System
子目录,里面通常有两个文件:System.hi
和 System.dyn_hi
。如果缺少前者,那是你的问题。
现在,您可能正在使用 Arch Linux。正如 "Problems with linking" 部分中关于 Arch Haskell wiki page 的文档所述,Arch Haskell 社区包(包括 haskell-random
)有意省略了接口文件和库的静态版本。
那里给出了几种解决方法:
- 您可以在使用 GHC 编译时使用动态链接。直接使用 GHC 时,这仅意味着传递
-dynamic
标志。对于基于 Cabal 的项目,该页面上给出了修改~/.cabal/config
以对所有项目使用动态链接的说明。 - 您可以安装
ghc-static
和ghc-pristine
包并设置路径 and/or Cabal 以使用/usr/share/ghc-pristine/bin/ghc
中的编译器,它将维护自己独立的包数据库不会干扰全局安装的 Haskell 社区包,例如haskell-random
. - 您可以安装
ghc-static
以获得基础库的静态版本,然后 运行cabal install --force-reinstalls somepackage
获取您需要的所有非基础包。请注意,Wiki 指出这可能既乏味又复杂,因为您必须手动确定所有包依赖项。
现在,看起来您已经安装了 ghc-static
,或者在调用 GHC 时您会 也 收到有关 [=32= 中丢失文件的错误] 包裹。你 运行 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
下),但它应该会恢复原样。