stack.yaml 文件和 .cabal 文件的区别?

stack.yaml file & .cabal file differences?

我最近开始为 Haskell 使用堆栈,为您的项目指定外部依赖项。有时你将它放在 .cabal 文件中,而有时你将它放在 .yaml 文件中。

当你把它放在 cabal 文件中时,它只会在堆栈存储库中查找你的包,我的想法是否正确。然而,当你将它放在你的 .yaml 文件中时,如果它在任何快照中都找不到它,它也会在 Hackage 服务器中搜索?

您项目的所有依赖项都进入 .cabal 文件。不过,您是对的,有时您还会在 stack.yaml 文件中列出包,这可能会造成混淆,这是可以理解的。这是为什么?

好吧,.cabal 文件始终表达您对包的依赖性,但 stack.yaml 文件有效地配置了 这些包的来源 。通常,当使用 stack 时,包来自 Stackage,基于您在 stack.yaml 文件中指定的 解析器 。但是,Stackage 并不包含 Hackage 中的所有包,而且它也不打算包含 - 当您需要位于 Stackage 之外的包时,您必须在 stack.yaml 文件中指定它们。

这是为什么?好吧,解析器自动将两条重要信息耦合在一起:包名称 包版本。 Stackage 解析器提供(弱)保证单个解析器中的所有包将协同工作,因此当包来自解析器时,无需手动选择您想要的版本。相反,Stackage 会为您做决定。

从 Hackage 中提取包时,您没有这种奢侈,因此您需要使用 extra-deps 指定包 它们的版本。例如,您可能有这样的内容:

extra-deps:
- crypto-pubkey-openssh-0.2.7
- data-bword-0.1
- data-dword-0.3

此条目具体确定应从 Hackage 而不是 Stackage 中提取哪些版本的软件包。


构建应用程序时,这似乎有点多余——您也可以在 .cabal 文件中指定版本约束,那么为什么要在 stack.yaml 文件中复制它们呢?但是,在构建库时,区别更显着:.cabal 文件表达了库的实际版本限制(如果有的话),而 stack.yaml 文件精确指定了实际安装的版本在本地开发时。

从这个意义上说,stack.yaml 文件的用途类似于其他包管理器的 Gemfile.locknpm-shrinkwrap.json 文件,尽管职责并不像stack(部分原因是关于 Haskell 的包系统如何工作的历史原因以及它过去遇到的一些问题)。