stack.yaml文件和.cabal文件有什么区别?

9

我最近开始在Haskell中使用stack,为项目指定外部依赖项时。有时你会把它放在.cabal文件中,而其他时候你会把它放在.yaml文件中。

我想知道,当你将其放入cabal文件中时,它只会在stackage存储库中查找您的软件包。然而,当你把它放在你的.yaml文件中时,如果在任何快照中都找不到它,它还会在Hackage服务器中搜索吗?


你所说的“将其放置在你的.yaml文件中”是什么意思?能给个例子吗? - ErikR
1个回答

15

您项目中所有的依赖关系都放在 .cabal 文件中。但是,有时您也会在 stack.yaml 文件中列出软件包,这可能会令人感到困惑。为什么呢?

嗯,.cabal 文件始终表示您对软件包的依赖关系,但是 stack.yaml 文件实际上配置了软件包来自哪里。通常情况下,使用 stack 时,软件包来自于您在 stack.yaml 文件中指定的 resolver 的 Stackage 。然而,Stackage 并不包括 Hackage 中的所有软件包,也不打算这样做——当您需要使用 Stackage 之外的软件包时,必须在 stack.yaml 文件中指定它们。

为什么会这样呢?因为 resolver 自动将两个重要信息捆绑在一起:软件包名称 及其 版本号。 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包系统的历史原因以及它过去存在的一些问题)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接