nix-shell为#! runghc的翻译

时间:2017-07-10 21:45:11

标签: haskell nix

我试图使用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的主机。

谢谢,

1 个答案:

答案 0 :(得分:7)

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

GHC和库包在nix中的工作方式可能与你期望的有点“内外”。实际上,您需要安装一个“依赖于”所需库的编译器,而不是简单地单独安装编译器和库。原因是GHC旨在通过修改安装GHC的文件树来添加库包。在只有单个系统GHC安装的可变文件系统上,您只需在安装库时修改GHC,但nix不能。 Nix必须能够安装永不改变的冷冻GHC,并且可能安装许多GHC。

所以会发生什么呢?你安装了一个小的包装器,它依赖于底层的“原始”GHC安装你想要使用的所有库。然后,包装器就像安装GHC一样,这些库已经注册了,而实际上并不需要复制整个GHC安装。当你只是自己安装一个库包时,它只是处于惰性状态,没有任何GHC只能通过它来找到它。

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

您需要做的是使用以下行:

nix-shell

您不是直接安装#! nix-shell -i runghc -p "ghc.withPackages (ps: [ ps.HTTP ])" ghc;相反,HTTP函数计算一个nix包,它安装一个知道ghc.withPackages Haskell包的GHC包装器。在引擎盖下,这取决于没有额外库的“原始”GHC,也取决于HTTP库,并且还将导致这些库的安装。

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