6 ms·
Not to diminish the Cabal problems here, but you run into similar problems with Maven as well. Version management is a real hard problem. Especially when there
by chopin 13y ago
Not to diminish the Cabal problems here, but you run into similar problems with Maven as well. Version management is a real hard problem. Especially when there is little awareness in producing compatible successors. Especially this problem made my experiences with Haskell somewhat bitter. But I have the same problem (in really productive code) with Maven. Writing a working Maven plugin can be made pretty challenging by that as especially the stuff you want to use in Maven plugins is burdened with incompatibilities.
So, Cabal is in good company in that regard.
- bjourne 13y agoHaskell packages like to specify requirements using both a lower bound and an upper bound. So package A depends on B being version 0.55 <= B < 0.99. Package C depends on B being version 0.90 <= B <= 1.35. So if you installed C before A you will get version 1.35 of B and will now need to either downgrade B or have two versions installed. Chaos ensues. Why Hackage packagers like to specify upper bounds I'm not sure of. Backwards compatibility either is very hard to achieve in Haskell or maintainers just don't care that much about it. I don't know about Maven so I can't say whether that is as bad. But at least pip, npm and gems are a breeze compared to cabal.
- massysett 13y ago"Why Hackage packagers like to specify upper bounds I'm not sure of." There is a policy that says you're supposed to do this: http://www.haskell.org/haskellwiki/Package_versioning_policy http://www.haskell.org/haskellwiki/Package_versioning_policy The idea is that by specifying upper bounds, the package is more likely to build after the dependencies change. This idea is subject to considerable controversy. http://www.haskell.org/pipermail/haskell-cafe/2012-August/102885.html http://www.haskell.org/pipermail/haskell-cafe/2012-August/10... There's also been more recent mailing list traffic on it, but my Google skills are failing me here and the arguments haven't changed all that much. My opinion is that we are relying too heavily on upper bounds to solve a whole bevy of interrelated, but separate, problems. Other solutions are evolving to help deal with some of the problems. cabal sandboxes allow you to build a package separately from your others, reducing dependency issues. cabal freeze will help you specify exact dependencies, including transitive ones. Another project, Stackage, aims to maintain a whole slew of packages in a buildable state: https://github.com/fpco/stackage https://github.com/fpco/stackage
- tredontho 13y agoI think the more recent issue you're referring to is this? http://www.haskell.org/pipermail/libraries/2014-February/022114.html http://www.haskell.org/pipermail/libraries/2014-February/022...
- bjourne 13y agoIt's an incredibly stupid policy. As others have noted, other package managers also has the capability of setting upper bounds on package versions and pip also has the ability to freeze your dependencies to specific versions. However those features aren't necessary to productively use pip for example. Because Python package maintainers are very good at maintaining backwards compatibility (or using deprecation cycles when those are needed) because people that depend on their packages get upset with them. The rules are different for beta releases because it's your own fault if you depend on them and their api changes. Precisely because specifying upper bounds is encouraged, Haskell maintainers seem to act as if they have a free card when it comes to backwards incompatible changes. In the long run that causes much more packaging troubles then specifying upper bounds saves. Perhaps there's nothing wrong with Haskell nor Cabal, but the Haskell community's way to handle backwards compatibility is wrong imo.
- mightybyte 13y agoUpper bounds are information about what you know your package works with. It makes no sense to throw this away. What does make sense is improving our tooling to allow this information to be ignored in certain circumstances. I've been on the other side of the fence with a large app written a long time ago that did not specify upper bounds. Now that app is essentially unbuildable given the time I'm willing to put in. If I and all my dependencies had followed the PVP and specified correct upper bounds everywhere, I would still be able to build my app today. No, I wouldn't be able to build it with the latest version of other libraries, but that's not what I want to do. If you don't specify upper bounds, the probability of your package building goes to ZERO in the long term. Not epsilon...zero. That's unacceptable for me. If it works today, I want it to work for years to come.
- 13y ago
- mightybyte 13y agoPackages are supposed to specify upper bounds because without them you can end up with spontaneous breakages when a transitive dependency several steps away changes in a backwards-incompatible way. Haskell has the PVP which can prevent this. It is pretty similar to Semantic Versioning (http://semver.org/ http://semver.org/). The upper bounds are not specified willy-nilly. They are specified in a way that includes backwards-compatible revisions, but excludes backwards-incompatible ones. I've been using Haskell for more than 6 years and in my experience the worst build problems happen with parts of the ecosystem that don't specify upper bounds. There's been a lot of discussion about this in the community. We're aware of the issues and we're working on solving them. One attractive possibility being discussed is adding a flag to cabal that allows one to ignore upper bounds. In theory this seems like it can preserve the benefits we get from the added information in an upper bound while eliminating the pain. An extension to this idea is to make two operators (say < and <!) that specify a "soft" upper bound that is just the highest you've been able to test against and a "hard" upper bound where you're telling cabal that your package is known to break. This extra information would make the solver much better when you tell it to ignore upper bounds because it would only ignore the ones that are safe to ignore. I suspect that this problem is more visible in Haskell than in other languages. Haskell's type system gives you a way to bound the number of things that you must understand about an API in order to use it. The confidence that we get from having these guarantees makes code reuse orders of magnitude easier in Haskell than it is in pretty much any other language in mainstream use today. Others have made this same observation. Here (https://www.youtube.com/watch?v=BveDrw9CwEg#t=903 https://www.youtube.com/watch?v=BveDrw9CwEg#t=903) is a presentation given at CUFP last year by a company using Haskell in production that gives the actual reuse numbers that they've seen for several different languages.
- DougBTX 13y ago> But at least pip, npm and gems are a breeze compared to cabal. I've not really used the others, but Gemfiles have the concept of upper bounds: http://stackoverflow.com/questions/5170547/what-does-tilde-greater-than-mean-in-ruby-gem-dependencies http://stackoverflow.com/questions/5170547/what-does-tilde-g... Docs: http://guides.rubygems.org/patterns/#pessimistic_version_constraint http://guides.rubygems.org/patterns/#pessimistic_version_con...
- copergi 13y ago>Why Hackage packagers like to specify upper bounds I'm not sure of Because having working code spontaneously break is very bad. You can't just blindly pretend any future versions of all your dependencies will work without updating your code. APIs change. So you specify the version range your code works with. >Backwards compatibility either is very hard to achieve in Haskell Backwards compatibility is the whole point of upper bounds. >But at least pip, npm and gems are a breeze compared to cabal. I had constant problems with pip. Because it will blindly install the latest 'foo' dependency even though the API changed and now my app is broken.
- Silhouette 13y agoYou can't just blindly pretend any future versions of all your dependencies will work without updating your code. APIs change. If you have a risk of arbitrary changes in APIs happening in any minor update, your infrastructure and dependency management are fundamentally flawed and ongoing development will always be difficult. There is nothing unique to Haskell about this, it's just software development 101, separating interface from implementation and all that jazz. There does seem to be a surprising... I'm not sure how to describe it, maybe a lack of respect?... for this principle in parts of the Haskell community, given the same community's obvious general preference for correctness and being sure everything fits together in a controlled way. Of course sometimes you want to make major changes to an API and maybe they break backward compatibility, but usually that is a Big Deal in software development, it doesn't normally just get done in some quick point release along with a couple of bug fixes and a security patch. I had constant problems with pip. Because it will blindly install the latest 'foo' dependency even though the API changed and now my app is broken. Not that I'm doubting you, but I do find that experience surprising. I work with Python all the time, on different kinds of projects but typically always using pip for package management, and I can't immediately think of a single time that's happened to me. Of course, you can also tell pip to install only within a specific version range if you ever need to.
- copergi 13y agoThat is the most elaborate strawman I have seen in a while. You are now literally saying "haskell is dumb because they do what I think they should do. They should do what they already do instead." >If you have a risk of arbitrary changes in APIs happening in any minor update You don't. API changes require changing the major version. Read the PVP. >There is nothing unique to Haskell about this Precisely my point. >Of course, you can also tell pip to install only within a specific version range if you ever need to. Same with cabal. So what is the problem again?