我正在尝试使用nix-shell作为#!runghc的包装器,如联机帮助页中所示.但它找不到图书馆.给出以下示例,从联机帮助页中删除
#! /usr/bin/env nix-shell
#! nix-shell -i runghc -p haskellPackages.HTTP
import Network.HTTP
main = return ()
Run Code Online (Sandbox Code Playgroud)
我得到以下结果:
[~: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]$
Run Code Online (Sandbox Code Playgroud)
在我看来,这正是nix-shell -p要避免的.
我做错了什么,错过了重点,还是有错误?这是在nixOS 17.03主机上,也是在Ubuntu上运行nix 17.09的主机.
谢谢,
您用于运行脚本的环境缺少一个步骤.它有一个GHC和一个HTTP包,但编译器不知道该包.
GHC和库包在nix中运行的方式可能与你期望的有点"内外".实际上,您需要安装一个"依赖于"所需库的编译器,而不是简单地单独安装编译器和库.原因是GHC旨在通过修改安装GHC的文件树来添加库包.在只有单个系统GHC安装的可变文件系统上,您只需在安装库时修改GHC,但nix不能.Nix必须能够安装永不改变的冷冻GHC,并且可能安装许多GHC.
所以会发生的是你安装一个小包装器,它依赖于底层的"原始"GHC安装和你想要使用的所有库.然后,包装器就像安装GHC一样,这些库已经注册了,而实际上并不需要复制整个GHC安装.当你只是自己安装一个库包时,它只是处于惰性状态,没有任何GHC只能通过现有的方式找到它.
实际上,您在此处显示的脚本实际上并没有指定它应该安装一个编译器; 它只是要求HTTP 图书馆.当我尝试你的剧本时,我得到了command not found: runghc.这runghc只是在你的系统上工作,因为它碰巧已经在你的路径中运行了(可能是因为你的配置文件中安装了GHC?),并且GHC没有与HTTP软件包一起安装,因此无法看到它.在nix-shell加入刚刚库环境于事无补.
你需要做的是使用这一行:
#! nix-shell -i runghc -p "ghc.withPackages (ps: [ ps.HTTP ])"
Run Code Online (Sandbox Code Playgroud)
你没有安装ghc或HTTP直接安装; 相反,该ghc.withPackages函数计算一个nix包,它安装一个知道HTTPHaskell包的GHC包装器.在引擎盖下,这取决于"原始"GHC,没有额外的库,也取决于HTTP库,并将导致那些也被安装.
如果您使用许多不同的Haskell环境(可能通过这样的nix-shell脚本,每个脚本需要一组不同的库),那么您最终会withPackages在系统上安装一个独特的包装器,用于您使用的每个库组合.但这没关系,因为包装器本身很小,而且nix能够在所有这些环境之间共享和重用底层GHC和库包.