Cabal 和 Stack 有什么区别?

What is the difference between Cabal and Stack?

昨天我了解到一个名为 Stack 的新 Haskell 工具。乍一看,它的功能与 Cabal 差不多。那么,它们之间有什么区别呢? Stack 是 Cabal 的替代品吗?在哪些情况下我应该使用 Stack 而不是 Cabal? Stack 能做什么而 Cabal 不能?

根据我从 FAQ 中收集到的信息,Stack 似乎使用了 Cabal 库,但没有使用 cabal.exe 二进制文件(更准确地称为 cabal-install)。看起来该项目的目标是自动沙盒和避免依赖地狱。

换句话说,它使用相同的 Cabal 包结构,只是提供了一个不同的前端来管理这些东西。 (我觉得!)

Is stack a replacement for Cabal?

是也不是

In which cases should I use Stack instead of Cabal? What can Stack do that Cabal can't?

Stack 按默认 使用精选的堆栈包。既然如此,已知任​​何依赖项都可以一起构建,从而避免版本冲突问题(当它们在 Haskell 体验中很常见时,曾经被称为 "cabal hell")。 Cabal 的最新版本也有防止冲突的措施。尽管如此,使用 Stack 设置一个可重现的构建配置,您可以在其中确切地知道将从存储库中提取什么。请注意,还有使用非堆栈包的规定,因此即使堆栈快照中不存在包,您也可以继续使用。

就个人而言,我喜欢 Stack 并会推荐每个 Haskell 开发人员使用它。他们的发展。而且它的用户体验好得多。还有一些 Stack 可以做而 Cabal 还没有提供的东西:

  • Stack 甚至会为您下载 GHC 并将其保存在一个独立的位置。
  • Docker 支持(部署您的 Haskell 应用程序非常方便)
  • Reproducible Haskell script: You can pinpoint version of a package and can get guarantee that it will always execute without any problem. (Cabal also has a script feature,但完全确保可重复性并不是那么简单。)
  • 有能力做到 stack build --fast --file-watch。如果您更改存在的本地文件,这将自动重建。将它与 --pedantic 选项一起使用对我来说是一个交易破坏者。
  • Stack 支持使用 templates 创建项目。它还支持您自己的自定义模板。
  • Stack 具有内置的 hpack 支持。它提供了一种使用 yaml 文件编写 cabal 文件的替代方法(IMO,一种更好的方法),这种方法在行业中使用更广泛。
  • Intero 体验流畅when working with Stack

有一个很好的博客 post 解释了不同之处:Why is Stack not Cabal? 虽然 Cabal 在之后的几年中 post 已经发展以克服所讨论的一些问题在那里,对 Stack 背后的设计目标和理念的讨论仍然相关。

在下文中,我将比较的两个工具称为 cabal-installstack。特别是,我将使用 cabal-install 来避免与 Cabal 库混淆,这是两个工具使用的通用基础结构。

从广义上讲,我们可以说 cabal-installstackCabal 的前端.这两种工具都可以构建 Haskell 个项目,这些项目的依赖项集可能在单个系统的范围内相互冲突。它们之间的主要区别在于它们如何实现这一目标:

  • 默认情况下,cabal-install 将在被要求构建项目时查看其 .cabal 文件中指定的依赖项并使用一个依赖项解决器来找出一组满足它的包和包版本。本集取自Hackage as a whole -- all packages and all versions, past and present. Once a feasible build plan is found, the chosen version of the dependencies will be installed and indexed in a database somewhere in ~/.cabal. Version conflicts between dependencies are avoided by indexing the installed packages according to their versions (as well as other relevant configuration options), so that different projects can retrieve the dependency versions they need without stepping on each other's toes. This arrangement is what the cabal-install documentation means by "Nix-style local builds".

  • 当被要求构建项目时,stack 将不会去 Hackage,而是查看 [=17= 的 resolver 字段] -- 不同的格式,相同的角色)仅使用快照提供的内容。从每个快照安装的包都注册在单独的数据库中,它们不会相互干扰。

我们可能会说,stack 方法在指定构建配置时以一些设置灵活性换取简单性。特别是,如果您知道您的项目使用 LTS 15.3 快照,您可以在使用 stack.

时转到 its Stackage page and know, at a glance, the versions of any dependency stack might pull from Stackage. That said, both tools offer features that go beyond the basic workflows so that, by and large, each can do all that the other does (albeit possibly in a less convenient manner). For instance, there are ways to freeze exact versions of a known good build configuration and to solve dependencies with an old state of Hackage with cabal-install, and it is possible to require non-Stackage dependencies or override snapshot package versions

最后,cabal-installstack 之间的另一个差异大到值得在本概述中提及的是 stack旨在提供一个完整的构建环境,具有automatic GHC installation management and Docker integration. In contrast, cabal-install is meant to be orthogonal to other parts of the ecosystem, and so it doesn't attempt to provide this sort of feature (in particular, GHC versions have to be installed and managed separately, for instance through the ghcup tool).

等功能