Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

stack.yaml file & .cabal file differences?

I have recently started using stack for Haskell, when specifying external dependencies for your project. Sometimes you place it in the .cabal file while other times you place it in the .yaml file.

Am I right in thinking that when you put it in the cabal file it only looks in the stackage repository for your packages. However when you place it in your .yaml file it also searches in the Hackage server, if it cannot find it in any of the snapshots?

like image 516
Zubair Avatar asked Aug 08 '16 22:08

Zubair


1 Answers

All of the dependencies for your project go into the .cabal file. You are correct, though, that sometimes you also list packages in the stack.yaml file, which can be understandably confusing. Why is that?

Well, the .cabal file always expresses your dependencies upon packages, but the stack.yaml file effectively configures where those packages come from. Usually, when using stack, packages come from Stackage based on the resolver you specify in the stack.yaml file. However, Stackage does not include all the packages in Hackage, and it is not intended to—when you need packages that live outside of Stackage, you have to specify them in the stack.yaml file.

Why is this? Well, the resolver automatically couples two important pieces of information together: package names and package versions. Stackage resolvers provide a (weak) guarantee that all of the packages within a single resolver will work together, so when a package comes from a resolver, there is no need to manually pick which version you want. Instead, Stackage will decide for you.

When pulling packages from Hackage, you do not have this luxury, so you need to specify packages and their versions using extra-deps. For example, you might have something like this:

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

This entry determines specifically which versions of which packages should be pulled from Hackage rather than Stackage.


When building an application, this might seem a little redundant—you can specify version constraints in the .cabal file, too, so why duplicate them in the stack.yaml file? However, when building a library, the distinction is a little more significant: the .cabal file expresses the actual version constraints of your library (if any), but the stack.yaml file specifies precisely which versions to actually install when developing locally.

In this sense, the stack.yaml file serves a purpose similar to the Gemfile.lock or npm-shrinkwrap.json files of other package managers, though the responsibilities are not nearly as clear-cut with stack (in part due to historical reasons around how Haskell’s package system works and some of the problems it’s had in the past).

like image 161
Alexis King Avatar answered Oct 20 '22 09:10

Alexis King