nix-shell为#!runghc的翻译

use*_*536 8 haskell nix

我正在尝试使用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的主机.

谢谢,

Ben*_*Ben 8

您用于运行脚本的环境缺少一个步骤.它有一个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)

你没有安装ghcHTTP直接安装; 相反,该ghc.withPackages函数计算一个nix包,它安装一个知道HTTPHaskell包的GHC包装器.在引擎盖下,这取决于"原始"GHC,没有额外的库,也取决于HTTP库,并将导致那些也被安装.

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

  • 哇,这是一个很好的解释,本.事实上,它完美无缺.一旦我有资格,我会建议对nix-shell的联机帮助页进行增强,但与此同时,非常感谢您花时间来解释什么以及为什么.你们两个都解决了我当前的问题,并让我能够以更深刻的理解来解决下一个问题. (2认同)