秘社和斯塔克有什么区别?

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

43400 次浏览

从我能从 FAQ 中收集到的信息来看,Stack 似乎使用 Cabal 库,而不是 cabal.exe二进制文件(更准确地说是 Cabal-install)。看起来这个项目的目标是自动沙箱和避免依赖地狱。

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

斯塔克是卡巴尔的替代品吗?

是也不是。

在什么情况下我应该使用 Stack 而不是 Cabal? Stack 能做什么 Cabal 不能做的事情?

Stack 通过 违约使用策划好的堆栈包。因此,我们知道任何依赖关系都是一起构建的,这样可以避免版本冲突问题(在 Haskell 经验中这种问题很常见,过去被称为“ Cabal hell”)。最近版本的秘社也有防止冲突的措施。尽管如此,使用 Stack 设置一个可重复的构建配置,使您确切地知道将从存储库中提取什么内容更加简单。请注意,还有使用非堆栈包的规定,所以即使堆栈快照中没有包,您也可以使用它。

就个人而言,我喜欢 Stack,并推荐每个哈斯克尔开发人员使用它。他们的发展是 很快。它有一个 很多更好的用户体验。有些事情 Stack 做到了 Cabal 还没有提供:

  • Stack 甚至会为您下载 GHC,并将其保存在一个独立的位置。
  • Docker 支持(这对于部署 Haskell 应用程序非常方便)
  • Reproducible Haskell script : 您可以精确定位一个包的版本,并且可以保证它总是可以毫无问题地执行。(Cabal 还有一个脚本功能,但是完全确保它的可重复性并不是那么简单。)
  • stack build --fast --file-watch的能力。如果更改存在的本地文件,这将自动重新生成。使用它连同 --pedantic选项是一个交易破坏者对我来说。
  • Stack 支持使用 模板创建项目,还支持自定义模板。
  • Stack 内置了 Hpack支持。它提供了另一种(IMO,一种更好的)使用 yaml 文件编写阴谋集团文件的方法,这种方法在工业中得到了更广泛的应用。
  • Intero 有一个顺利的经验 和 Stack 一起工作的时候

有一篇很好的博客文章解释了这种差异: 为什么 Stack 不是 Cabal?虽然 Cabal 在那篇文章之后的几年里已经发展到克服了那里讨论的一些问题,但是关于 Stack 背后的设计目标和哲学的讨论仍然是相关的。

在接下来的内容中,我将把这两个工具作为 阴谋安装进行比较。特别是,我将使用 阴谋安装来避免与 秘社库混淆,秘社库是两种工具都使用的公共基础设施。

广义地说,我们可以说 阴谋安装秘社的前锋。这两个工具都可以构建 Haskell 项目,它们的依赖集可能在单个系统的范围内相互冲突。它们之间的关键区别在于如何实现这一目标:

  • 默认情况下,当被要求构建项目时,阴谋安装将查看其 .cabal文件中指定的依赖项,并使用依赖求解器计算出一组满足它的包和包版本。这个集合是从 黑客入侵作为一个整体——过去和现在的所有包和所有版本中抽取的。一旦找到可行的构建计划,将在 ~/.cabal中的某个数据库中安装所选择的依赖项版本并建立索引。依赖项之间的版本冲突可以通过根据版本(以及其他相关配置选项)对安装的包进行索引来避免,这样不同的项目就可以检索它们需要的依赖项版本,而不会彼此干扰。这种安排就是 阴谋安装文档中 “ Nix 风格的本地建筑”的含义。

  • 当被要求建立一个项目时,将会考虑到 stack.yamlresolver领域,而不是去 Hackage。在默认工作流中,该字段指定 堆叠 快照,它是具有已知相互兼容的 修好了版本的 Hackage 包的子集。然后,将尝试仅使用快照提供的内容来满足 .cabal文件(或者可能是 stack.yaml0——不同格式,同一角色)中指定的依赖项。从每个快照安装的包都在单独的数据库中注册,这些数据库不会相互干扰。

我们可以说,在指定构建配置时,方法用一些设置灵活性换取了一些直观性。特别是,如果您知道您的项目使用了,比如说,LTS 15.3快照,您可以访问 它的堆栈页面,一眼就可以知道从 Stackage 获取的任何依赖关系 的版本。也就是说,这两种工具都提供了超越基本工作流的特性,因此,总的来说,它们都可以完成对方所做的一切(尽管可能是以一种不那么方便的方式)。例如,使用 阴谋安装可以实现 冻结已知的良好构建配置的精确版本用旧的 Hackage 状态解决依赖关系,使用 实现 需要非堆栈依赖项或覆盖快照包版本也是可能的。

最后,阴谋安装之间的另一个不同之处是,旨在提供一个完整的构建环境,具有诸如 自动 GHC 安装管理码头整合这样的特性。相比之下,阴谋安装意味着与生态系统的其他部分是正交的,所以它不会尝试提供这种特性(特别是,GHC 版本必须单独安装和管理,例如通过 打孔器)。