views:

121

answers:

3

In the dependencies section of a cabal file:

Build-Depends: base >= 3 && < 5, transformers >= 0.2.0

Should I be doing something like

Build-Depends: base >= 3 && < 5, transformers >= 0.2.0 && < 0.3.0

(putting upper limits on versions of packages I depend on)

or not?

I'll use a real example: my "List" package on Hackage (List monad transformer and class)

  • If I don't put the limit - my package could break by a change in "transformers"
  • If I do put the limit - a user that uses "transformers" but is using a newer version of it will not be able to use lift and liftIO with ListT because it's only an instance of these classes of transformers-0.2.x

I guess that applications should always put upper limits so that they never break, so this question is only about libraries:

Shall I use the upper version limit on dependencies or not?

+1  A: 

IMO putting upper bounds on the accepted version numbers is the right thing to do. Given the semantics of version numbers used by Hackage there is certainly no guarantee that your package will work with, in this case, transformers 0.3.0.

I haven't seen any real discussion about this though and there doesn't seem to be a general recommendation to use upper bounds except for the base package.

svenningsson
+2  A: 

Think about the failure modes:

  • With the upper bound, either your package builds or cabal bleats about an unsatisfied build dependency. Blame is clearly assigned.

  • Without the upper bound, customer has a recent version of transformers and it's not backwards compatible. Your software fails to build; GHC bleats about how your code doesn't compile. Your software looks shoddy.

Put in the upper bound.

Norman Ramsey
@Norman Ramsey: With the upper bound, cabal will not bleat about an unsatisfied build dependency, I tested it and it prints "Warning: This package indirectly depends on multiple versions of the samepackage. This is highly likely to cause a compile failure.". Then the customer package will probably fail to compile because of a missing instance
yairchu
@yairchu: does that mean that a package you imported into your package depends on `transformers`, but has different version constraints?
jberryman
@jberryman: exactly. my test package depends on List which depends on transformers >= 0.2.0 and on MaybeT-transformers that depends on transformers 0.1.*
yairchu
@yairchu, @jberryman: Bad on cabal! That is kind of a bleat, but not enough. You should have to give it some kind of `-force` option to get it to continue. I'll file a bug report.
Norman Ramsey
@Norman Ramsey: I think that it's good that this is just a warning and not an error. There's a significant chance that all will work well even though multiple versions of the same package are used. This allows for more interoperability while pushing developers to update their code by means of a warning.
yairchu
+4  A: 

There is an explicit policy recommending upper bounds - see in particular section 3 ("Dependencies in Cabal"). The other answers give some further justification for this policy.

In short - the upper limit should be in form of < A.(B+1) where A and B are the first elements of the current version (A.B.C...). This is because increasing A.B should mean that the version breaks old APIs.

Ganesh Sittampalam
@Ganesh Sittampalam: I added a quick summary of the mentioned policy to your answer. I hope you don't mind, but if you do, feel free to change/rephrase/revert it.
yairchu