nix-shell 作为#! runghc的翻译

nix-shell as #! interpreter for runghc

我正在尝试使用 nix-shell 作为 #! runghc 的包装器,如联机帮助页中所建议。但它找不到图书馆。给定以下示例,从联机帮助页

中删减
#! /usr/bin/env nix-shell
#! nix-shell -i runghc -p haskellPackages.HTTP

import Network.HTTP

main = return ()

我得到以下结果:

[~:0]$ ./nixshelltest 

nixshelltest:4:1: error:
    Failed to load interface for ‘Network.HTTP’
    Use -v to see a list of the files searched for.
[~:1]$ 

在我看来,这正是 nix-shell -p 要避免的。

我是不是做错了什么,漏掉了重点,还是有错误?这既在 nixOS 17.03 主机上,也在 Ubuntu.

之上的主机 运行 nix 17.09

谢谢,

您用于 运行 脚本的环境缺少一个步骤。它有一个 GHC 和一个 HTTP 包,但编译器不知道该包。

GHC 和库包在 nix 中的工作方式可能 "inside out" 与您的预期有些出入。您实际上需要安装一个 "depends on" 所有您想要的库的编译器,而不是简单地单独安装编译器和库。原因是GHC被设计成通过修改安装GHC的文件树来添加库包。在只有一个系统 GHC 安装的可变文件系统上,您只需在安装库时修改 GHC,但 nix 不能。 Nix 必须能够安装一个永远不会改变的冻结 GHC,而且可能有很多。

所以你安装了一个小包装器,它依赖于底层 "raw" GHC 安装 所有你想使用的库.然后,包装器就像安装了已注册这些库的 GHC,实际上不需要复制整个 GHC 安装。当你自己安装一个库包时,它只是呆呆地呆在那里,没有任何 GHC 能够仅仅通过它现有的来找到它。

事实上,您在此处显示的脚本实际上并没有指定它应该安装编译器;它 只是 请求 HTTP 。当我尝试你的脚本时,我得到了 command not found: runghcrunghc 只在你的系统上工作,因为当你 运行 时它恰好已经在你的路径中(可能是因为你的配置文件中安装了 GHC?),并且 GHC 没有安装HTTP 包,所以看不到它。 nix-shell 仅将库添加到环境中没有帮助。

您需要做的是使用这一行:

#! nix-shell -i runghc -p "ghc.withPackages (ps: [ ps.HTTP ])"

您没有直接安装 ghcHTTP;相反,ghc.withPackages 函数计算一个 nix 包,该包安装了一个了解 HTTP Haskell 包的 GHC 包装器。在引擎盖下,这取决于 "raw" GHC,没有额外的库,也取决于 HTTP 库,也会导致安装这些库。

如果您使用许多不同的 Haskell 环境(可能通过这样的 nix-shell 脚本,每个脚本都需要一组不同的库),那么您最终会得到一个独特的 withPackages 在您的系统上为您使用过的每个库组合安装的包装器。但这没关系,因为包装器本身很小,而且 nix 能够在所有这些环境之间共享和重用底层 GHC 和库包。