我试图使用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的主机。
谢谢,
答案 0 :(得分:7)
您用于运行脚本的环境缺少一个步骤。它有一个GHC和一个HTTP包,但编译器不知道该包。
GHC和库包在nix中的工作方式可能与你期望的有点“内外”。实际上,您需要安装一个“依赖于”所需库的编译器,而不是简单地单独安装编译器和库。原因是GHC旨在通过修改安装GHC的文件树来添加库包。在只有单个系统GHC安装的可变文件系统上,您只需在安装库时修改GHC,但nix不能。 Nix必须能够安装永不改变的冷冻GHC,并且可能安装许多GHC。
所以会发生什么呢?你安装了一个小的包装器,它依赖于底层的“原始”GHC安装和你想要使用的所有库。然后,包装器就像安装GHC一样,这些库已经注册了,而实际上并不需要复制整个GHC安装。当你只是自己安装一个库包时,它只是处于惰性状态,没有任何GHC只能通过它来找到它。
实际上,您在此处显示的脚本实际上并没有指定它应该安装一个编译器; 只是要求HTTP
库。当我尝试你的脚本时,我得到了command not found: runghc
。 runghc
仅适用于您的系统,因为它恰好在您运行它时已经在您的路径中(可能是因为您的配置文件中安装了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和库包。