【问题标题】:Using hoogle in a haskell development environment on nix在 nix 上的 haskell 开发环境中使用 hoogle
【发布时间】:2015-02-27 23:58:02
【问题描述】:

我正在尝试在 Haskell 开发环境中使用 hoogle 就像O'Charles' wiki描述的那样:

为了使用hoogleLocal,我已经像下面这样修改了shell.nix,但它似乎没有为我安装hoogle 二进制文件。

let
  pkgs = import <nixpkgs> {};

  # I'm attempting to use hoogle here, but it is not working.
  haskellPackages =
    let callPackage = pkgs.lib.callPackageWith haskellPackages;
    in pkgs.recurseIntoAttrs (pkgs.haskellPackages.override {
      extension = self: super: {
        thiscurrentpackage = self.callPackage ./. {};
        hoogleLocal = pkgs.haskellPackages.hoogleLocal.override {
          packages = self.thiscurrentpackage;
        };
      };
    });
in pkgs.myEnvFun {
  name = haskellPackages.thiscurrentpackage.name;
  buildInputs = [
    (haskellPackages.ghcWithPackages (hs: ([
      hs.cabalInstall
      hs.ghcMod
      hs.yesodBin
      # This doesn't appear to install the hoogle binary?
      hs.hoogleLocal
    ] ++ hs.thiscurrentpackage.propagatedNativeBuildInputs)))
  ];
}

在生成的 shell 中,hoogle 二进制文件不可用。

如果我在buildInputs 中包含hs.hoogle,则会安装hoogle 二进制文件,但它找不到数据库。以下是我尝试使用它时发生的情况。

$ nix-shell
......
$ hoogle Monad
Could not find some databases: default
Searching in:
  .
    /nix/store/91y9q2y5a2ws8xgcsx1gkhfagc0f2qz6-haskell-hoogle-ghc7.8.3-4.2.36-shared/share/x86_64-linux-ghc-7.8.3/hoogle-4.2.36/databases

    There are no available databases, generate them with: hoogle data
$ hoogle data
    hoogle: /nix/store/91y9q2y5a2ws8xgcsx1gkhfagc0f2qz6-haskell-hoogle-ghc7.8.3-4.2.36-shared/share/x86_64-linux-ghc-7.8.3/hoogle-4.2.36/databases:
changeWorkingDirectory: does not exist (No such file or directory)
$

对于 O'Charles 所描述的设置,我如何才能使其正常工作?

编辑:原来的shell.nix与this answer中的相同。

【问题讨论】:

    标签: haskell nixos hoogle


    【解决方案1】:

    这是我的 Nix Haskell 开发环境的样子

    ~/.nixpkgs/config.nix:

    环境辅助函数

    首先,定义一个 haskellEnvFun 函数来构建 Haskell 环境:

    packageOverrides = super: rec {
    
    haskellEnvFun = { withHoogle ? false, compiler ? null, name }:
      let hp = if compiler != null
                 then super.haskell.packages.${compiler}
                 else haskellPackages;
    
          ghcWith = if withHoogle
                      then hp.ghcWithHoogle
                      else hp.ghcWithPackages;
    
      in super.buildEnv {
        name = name;
        paths = [(ghcWith myHaskellPackages)];
      };
    

    定义一些环境

    调用此函数来定义两种环境:一种用于在更改时运行 Hoogle 构建器,一种不用于:

    haskellEnvHoogle = haskellEnvFun {
      name = "haskellEnvHoogle";
      withHoogle = true;
    };
    
    haskellEnv = haskellEnvFun {
      name = "haskellEnv";
      withHoogle = false;
    };
    

    定义你想在本地 Haskell 开发环境中使用的所有包:

    myHaskellPackages = hp: with hp; [
      Boolean
      HTTP
      HUnit
      MissingH
      QuickCheck
      SafeSemaphore
      Spock
      aeson
      async
      attoparsec
      bifunctors
      blaze-builder
      blaze-builder-conduit
      blaze-builder-enumerator
      blaze-html
      blaze-markup
      blaze-textual
      cased
      cassava
      cereal
      comonad
      comonad-transformers
      directory_1_2_4_0
      dlist
      dlist-instances
      doctest
      exceptions
      fingertree
      foldl
      free
      hamlet
      hashable
      hspec
      hspec-expectations
      html
      http-client
      http-date
      http-types
      io-memoize
      keys
      language-c
      language-javascript
      language-bash
      lens
      lens-action
      lens-aeson
      lens-datetime
      lens-family
      lens-family-core
      lifted-async
      lifted-base
      linear
      list-extras
      list-t
      logict
      mime-mail
      mime-types
      mmorph
      monad-control
      monad-coroutine
      monad-loops
      monad-par
      monad-par-extras
      monad-stm
      monadloc
      mongoDB
      monoid-extras
      network
      newtype
      numbers
      optparse-applicative
      parsec
      parsers
      pcg-random
      persistent
      persistent-mongoDB
      persistent-template
      pipes
      pipes-async
      pipes-attoparsec
      pipes-binary
      pipes-bytestring
      pipes-concurrency
      pipes-csv
      pipes-extras
      pipes-group
      pipes-http
      pipes-mongodb
      pipes-network
      pipes-parse
      pipes-safe
      pipes-shell
      pipes-text
      posix-paths
      postgresql-simple
      pretty-show
      profunctors
      random
      reducers
      reflection
      regex-applicative
      regex-base
      regex-compat
      regex-posix
      regular
      relational-record
      resourcet
      retry
      rex
      safe
      sbv
      scotty
      semigroupoids
      semigroups
      shake
      shakespeare
      shelly
      simple-reflect
      speculation
      split
      spoon
      stm
      stm-chans
      stm-stats
      streaming
      streaming-bytestring
      streaming-wai
      strict
      stringsearch
      strptime
      syb
      system-fileio
      system-filepath
      tagged
      taggy
      taggy-lens
      tar
      tardis
      tasty
      tasty-hspec
      tasty-hunit
      tasty-quickcheck
      tasty-smallcheck
      temporary
      test-framework
      test-framework-hunit
      text
      text-format
      time
      tinytemplate
      transformers
      transformers-base
      turtle
      uniplate
      unix-compat
      unordered-containers
      uuid
      vector
      void
      wai
      wai-conduit
      warp
      wreq
      xhtml
      yaml
      zippers
      zlib
    ];
    

    外壳助手

    在您的 ~/.profile 中定义几个 bash 函数以方便加载这些环境:

    环境类型(){ 环境类型="$1" 转移 nix-shell -Q -p $envtype "$@" } haskell-env () { 环境类型“haskellEnv”“$@” } haskell-env-hoogle () { 环境类型“haskellEnvHoogle”“$@” }

    胡歌

    在你的 shell 中调用haskell-env-hoogle。这将构建您所有的包 + 文档并将您加载到具有hoogle 范围的环境中。此时我通常会输入:

    hoogle server --local -p 8080 &> /tmp/hoogle.log & disown
    

    在后台启动一个hoogle server。最终我想为此提供一个 systemd 服务,以便我可以通过 nixos-rebuild 重新生成文档并自动启动服务器。

    Emacs

    对于 emacs,我将 haskell-hoogle-url 设置为 http://localhost:8080/?hoogle=%s,这样我就可以获取光标下关键字的本地 hoogle 文档。我使用 spacemacs,所以我只需键入 , h h 即可获得此功能。

    您可以在此处查看我的完整 nixpkgs 配置:https://github.com/jb55/nix-files/blob/659798f2ca81fb7ad0cb5a29de576024ee16eef8/nixpkgs/config.nix#L20

    希望对您有所帮助。

    【讨论】:

      【解决方案2】:

      haskellPackages.hoogleLocal 似乎已过时;它已经不存在了。

      William Casarin 的回答似乎是假设您将使用一个单一的“haskell 开发环境”,而不是使用 nix-shell 为不同的项目提供不同的开发环境。

      我刚刚想出的办法是编写我的 shell.nix 以覆盖 ghc.withPackagesghcWithPackagesghc.withHoogle,这样当 nix-shell 创建一个带有 GHC 的环境时,它知道关于所有必要的包,它还会创建一个知道相同包的 hoogle 数据库。

      这是我的 shell.nix1

      { nixpkgs ? import <nixpkgs> {}, compiler ? "default", withHoogle ? true }:
      
      let
      
        inherit (nixpkgs) pkgs;
      
        f = import ./default.nix;
      
        packageSet = (
          if compiler == "default"
            then  pkgs.haskellPackages
            else  pkgs.haskell.packages.${compiler}
        );
      
        haskellPackages = (
          if withHoogle
            then  packageSet.override {
                    overrides = (self: super:
                      {
                        ghc = super.ghc // { withPackages = super.ghc.withHoogle; };
                        ghcWithPackages = self.ghc.withPackages;
                      }
                    );
                  }
            else  packageSet
        );
      
        drv = haskellPackages.callPackage f {};
      
      in
      
        if pkgs.lib.inNixShell then drv.env else drv
      

      我对 nix 很陌生,但我相信这应该是“独立于项目”的;当我更改它时,我可以使用cabal2nix . &gt; default.nix 从我的 cabal 文件中生成一个 nix 包,而无需触摸 shell.nix。

      我还没有真正在实际开发中使用它,只是我用来尝试弄清楚如何让 hoogle 在 nix-shell 中工作的一个虚拟项目。


      1这是cabal2nix --shell 吐出的骨架,删除了项目特定的内脏并用f = import ./default.nix 替换,而不是再次嵌入nixified cabal 包。

      【讨论】:

      • 是的!我曾经这样做过。在编写大量 Haskell 代码时,我发现将所有内容都放在一个 shell 中以进行快速开发更容易。但是,如果您只有一个正在从事的项目,这将非常有用。
      【解决方案3】:

      使用@Ben 的答案作为参考,这里是我需要对cabal2nix --shell 文件进行必要更改的差异:

      diff --git a/shell.nix b/shell.nix
      index 540ade3..e207d6e 100644
      --- a/shell.nix
      +++ b/shell.nix
      @@ -1,4 +1,4 @@
      -{ nixpkgs ? import <nixpkgs> {}, compiler ? "default", doBenchmark ? false }:
      +{ nixpkgs ? import <nixpkgs> {}, compiler ? "default", doBenchmark ? false , withHoogle ? true}:
      
       let
      
      @@ -21,10 +21,23 @@ let
               license = stdenv.lib.licenses.bsd3;
             };
      
      -  haskellPackages = if compiler == "default"
      +  haskellPackages' = if compiler == "default"
                              then pkgs.haskellPackages
                              else pkgs.haskell.packages.${compiler};
      
      +  haskellPackages = (
      +    if withHoogle
      +    then  haskellPackages'.override {
      +      overrides = (self: super:
      +        {
      +          ghc = super.ghc // { withPackages = super.ghc.withHoogle; };
      +          ghcWithPackages = self.ghc.withPackages;
      +        }
      +      );
      +    }
      +    else haskellPackages'
      +  );
      +
         variant = if doBenchmark then pkgs.haskell.lib.doBenchmark else pkgs.lib.id;
      
         drv = variant (haskellPackages.callPackage f {});```
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-02-17
        • 2015-12-27
        • 1970-01-01
        • 2015-01-03
        • 2013-10-15
        • 2018-07-28
        • 2012-08-11
        • 2012-02-23
        相关资源
        最近更新 更多