【问题标题】:nix-shell as #! interpreter for runghcnix-shell 为 #! runghc 的解释器
【发布时间】:2017-07-10 21:45:11
【问题描述】:

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

谢谢,

【问题讨论】:

    标签: haskell nix


    【解决方案1】:

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

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

    因此发生的情况是您安装了一个小型包装器,该包装器依赖于底层的“原始”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 包,该包安装一个 GHC 包装器,该包装器知道 HTTP Haskell 包。在底层,这取决于没有额外库的“原始”GHC,还取决于 HTTP 库,并且也会导致安装这些库。

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

    【讨论】:

    • 哇,这是一个很好的解释,本。确实,它运行良好。一旦我获得资格,我将建议对 nix-shell 的联机帮助页进行改进,但与此同时,非常感谢您花时间解释什么和为什么。您既解决了我眼前的问题,又使我能够以更深入的理解解决下一个问题。
    • @user3416536 可能是需要改进的nixos.org/nixpkgs/manual/…?我个人觉得“如何使用库安装编译器”部分没有突出显示。
    • @user3416536 不幸的是,nix-shell 手册页并不足以将它用于所有内容。这一点并不是 nix-shell 如何工作(甚至 nix 如何工作)的结果,而是 GHC 如何工作以及用于支持 GHC 环境的特定 nix 代码如何工作的结果。在 nix 中还有其他以这种方式工作的语言(python 就是其中之一),但也有其他语言不这样做。在 nix-shell 手册页中专门描述这一点并不合适,但这意味着除非您知道 nixpkgs 手册中有特定的 Haskell 部分,否则不清楚为什么您的脚本不起作用。 :(
    • @user3416536 一般来说,对于 nix,“最终用户程序”似乎很容易被遗忘,但是对于具有大量可独立安装部件(如编程语言库)的相当技术性的东西,您通常必须知道相当多的关于描述它们的 nix 代码如何工作以便在 nix 系统上使用它们。
    • 你的观点对于 nix-shell 手册页来说可能太深了,但它确实有一个 haskell“脚本”的例子,我认为这个例子应该有效!我认为应该纠正这个例子。否则删除(如果我们认为更正它会使手册页过于复杂)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-09
    • 2016-01-06
    • 2021-12-20
    • 2017-05-02
    • 1970-01-01
    • 1970-01-01
    • 2021-01-02
    相关资源
    最近更新 更多