栈是如何解决依赖关系的?

How does stack resolve dependencies?

栈是如何解决依赖冲突的?

我刚开始使用 Haskell,我对堆栈如何解决依赖关系几乎没有疑问。

  1. 假设我的项目需要 lib Alib B

    在内部,lib A 需要 lib X-1.9.0lib B 需要 lib X-2.0.0,堆栈如何解决这个问题?

    stack 文档说他们使用 snapshots 来解决冲突,这是如何工作的?这是否意味着 lib A 和 lib B 的作者决定了一个与它们都兼容的 lib X 版本?如果是这样,当我使用较新版本的 lib A 或 lib B 或者它们中的任何一个不在快照中时会发生什么?

    快照实际上是如何制作的?

  2. Stack 默认在全局安装包。当项目 A 需要 lib Y-1.0 而项目 B 需要 lib Y-1.1 时会发生什么?这是如何处理的?

  3. 如何使用 "stackage.org" 的软件包?

    我正在尝试安装 beam-core,但 google 将我带到了 https://www.stackage.org/package/beam-core,其中没有提及安装它的命令或最新版本是什么。我无法在 github 版本中的任何地方找到版本号。

    pip 和 npm 都非常简单,所有关于如何安装和使用的信息都可以在包的页面上找到。例如两者,

    https://pypi.org/project/bencode.py/

    https://www.npmjs.com/package/projects

    包含版本号和安装命令,尽管它们很明显。

  4. 我在尝试安装软件包时经常遇到与 'stack-configuration' 相关的错误。我不知道 'stack-configuration' 是什么? 所有这些错误是什么意思以及如何在上述所有问题的上下文中解决它们?

执行 stack install beam-corestack repl --package beam-core --package beam-sqlite --package sqlite-simple --package beam-migrate --package text 结果

`Users/username/Documents/beam-learn/beam-learn.cabal was modified manually. Ignoring   /Users/username/Documents/beam-learn/package.yaml in favor of the cabal file.
If you want to use the package.yaml file instead of the cabal file,
then please delete the cabal file.
Stack has not been tested with GHC versions above 8.6, and using 8.8.2, this may fail
Stack has not been tested with Cabal versions above 2.4, but version 3.0.1.0 was found, this may fail

Error: While constructing the build plan, the following exceptions were encountered:

In the dependencies for hashable-1.2.7.0:
    base-4.13.0.0 from stack configuration does not match >=4.4 && <4.13  (latest matching version is 4.12.0.0)
needed due to beam-core-0.8.1.0 -> hashable-1.2.7.0

Some different approaches to resolving this:

  * Set 'allow-newer: true' in /Users/username/.stack/config.yaml to ignore all version constraints and build anyway.

  * Build requires unattainable version of base. Since base is a part of GHC, you most likely need to use a different GHC version with the matching base.

Plan construction failed.`

对于问题 #1:

Stack 的设计理念是,对于给定的 Stack 项目,将仅使用给定包的一个版本。因此,如果您有一个需要库 AB 的项目,并且每个库都依赖于不同版本的库 X,那么您无法使用 Stack 按原样构建项目。

快照是通过构建包版本的集合(每个包只有一个版本)来构建的,这样所有包间的依赖关系都可以得到满足。这是由 Stackage "curators" as described here using the curator 工具完成的。 curator 工具使用 Hackage 上可用的包索引来构建一组版本的包(每个包恰好一个版本),它们在满足所有包相互依赖性的意义上是兼容的。

因此,库作者无需决定可同时使用两者的 X 版本。相反,他们需要指定 范围 X 版本,而 curator 工具会选择最新版本的 X ] 适用于他们的包,以及依赖于 XX 具有依赖性的其他人的包。

如果您想使用更新版本的库 AB,但快照中没有,您可以将其添加为构建计划中的额外依赖项(即,在extra-deps 文件的 stack.yaml 部分)。如果新版本无法使用快照版本 X 构建,您还需要为 X 添加额外的依赖项。如果这破坏了其他包并且您找不到一组额外的依赖项来解决所有冲突,那您就不走运了。

在实践中,因为大多数包具有相对宽泛的依赖范围,并且对于积极维护的包,这些范围通常与较新的兼容依赖版本保持同步,所以您通常 运行 无法解决冲突,但它确实发生了。

对于问题 #2:

Stack 并不真正在全局安装包。它在按快照组织的全局缓存(在 Linux 上,在目录 ~/.stack 中)安装快照包。因此,可以在不同快照下的此缓存中安装多个版本,项目将使用适合项目所选快照的版本。

对于问题 #3:

beam-core 的 Stackage 页面上,您可以看到包含它的最新 LTS 快照是 lts-14.27。您可以使用此解析器创建一个新项目:

$ stack new --resolver lts-14.27 my-beam-project

要将 beam-core 添加到您的项目,请编辑 my-beam-project/package.yaml 并添加依赖项:

dependencies:
- base >= 4.7 && < 5
- beam-core           # <-- add this

现在,运行 stack build 在您的 my-beam-project 目录中:

$ cd my-beam-project
$ stack build

它将构建 beam-core 及其所有依赖项,这需要几分钟时间,除非您之前已为此快照构建 beam-core

您可以 fiddle 通过 运行ning stack ghci 在您的项目中使用 beam-core

$ stack ghci
...
Configuring GHCi with the following packages: my-beam-project
GHCi, version 8.6.5: http://www.haskell.org/ghc/  :? for help
[1 of 2] Compiling Lib              ( /u/buhr/src/overflow/my-beam-project/src/Lib.hs, interpreted )
[2 of 2] Compiling Main             ( /u/buhr/src/overflow/my-beam-project/app/Main.hs, interpreted )
Ok, two modules loaded.
Loaded GHCi configuration from /tmp/haskell-stack-ghci/e5a80991/ghci-script
*Main Lib> import Database.Beam
*Main Lib Database.Beam> :t fieldName
fieldName
  :: Functor f =>
     (text-1.2.3.1:Data.Text.Internal.Text
      -> f text-1.2.3.1:Data.Text.Internal.Text)
     -> TableField table ty -> f (TableField table ty)
*Main Lib Database.Beam>

当然,您可以使用 beam-core 包在 src/Lib.hs and/or app/Main.hs 中添加代码。

对于问题 #4:

如评论中所述,我认为您遇到的问题是最新的 LTS 是 lts-15.3,而 beam-core 当前未为此快照构建。

因为beam-core为以前的快照构建的,而不是为当前快照构建的,所以它被排除在外可能是有充分理由的。在这种情况下,维护者似乎没有升级它以使用最新的 GHC 版本。具体来说,beam-core-0.8.0.0 的最新版本需要 hashable < 1.3 的版本,但满足该约束的最新版本是 hashable-1.2.7.0,它需要 base < 4.13。而且,虽然它远非显而易见,但这意味着它不适用于 GHC 8.8,仅适用于 GHC 8.6,因此您必须返回到 GHC 8.6 系列 Stackage 快照。