# The ^\>= operator in .cabal files

**URL:** <https://discourse.haskell.org/t/the-operator-in-cabal-files/6938>\
**Category:** Uncategorized\
**Created:** [July 10, 2023, 12:28pm UTC](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938 "2023-07-10T12:28:47Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![david-christiansen](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/david-christiansen/32/2404_2.png) [@david-christiansen](https://discourse.haskell.org/u/david-christiansen)\
**Post date:** [July 10, 2023, 12:28pm UTC](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938/1 "2023-07-10T12:28:47Z")

</div>

I was in a meeting today and I was pointed to a few places where users expressed surprise that `somelib ^>= 1.2.3` is not completely identical to a combination of `somelib >= 1.2.3` and `somelib < 1.3`. I remember when the operator was first introduced, it took me a bit of time to assimilate the documentation for it, so I figured I’d try to describe it in a bit of a different way, together which my understanding of the context.

The [documentation for the `build-depends` field](https://cabal.readthedocs.io/en/latest/cabal-package.html#pkg-field-build-depends) begins by describing the general syntax for library dependency version constraints, given using the `>`, `>=`, `==`, `<=`, and `<` operators combined using `&&` and `||`.

Much of the tooling around Cabal is intended to support a declarative workflow where a package states the requirements that it places on its dependencies, and then a solver identifies a set of specific versions that satisfies all requirements. This led to the development of the [Package Versioning Policy](https://pvp.haskell.org/), a forerunner of the now-widespread semver. One of the PVP’s requirements is that packages have upper bounds - rather than specifying `somelib >= 2.4.3`, one must specify `somelib >=2.4.3 && < 2.5`.

This specification of upper bounds has a key limitation: there’s no way to tell the difference between “2.5 doesn’t exist yet, so we’d better protect our users for when it comes out” and “I just tested with 2.5, and they changed that thing I depend on in such a way that I can’t work with both 2.4.x and 2.5.x at the same time”. Let’s call these two scenarios “conservative” and “definite” upper bounds. Without knowing the difference, build tools have to treat all upper bounds as if they are definite to avoid doing the wrong thing.

It’s nice for the build tool to know whether an upper bound is conservative or definite, but there was no way to state this in `.cabal` files until around 2017. For the sake of backwards compatibility, `<` constraints are still treated as if they are definite. But since 2017, `somelib ^>= 3.4.2` is a way to describe a conservative upper bound on a major version. In other words, `somelib ^>= 3.4.2` is usually treated the same as `somelib >= 3.4.2 && < 3.5`, as the PVP would require. However, it _additionally_ indicates that the upper bound of `3.5` is a conservative one, rather than a definite one - it’s got to be there for the sake of reliably constructing build plans, but if we do have to try bumping an upper bound, that one would be the first to try.

`cabal-install` uses this in a project configuration file to allow upper bounds to be ignored selectively. In particular, in `cabal.project`, the line:

```nohighlight
allow-newer: somelib

```

means to ignore _all_ upper bounds for `somelib`, while

```nohighlight
allow-newer: ^somelib

```

ignores only the _conservative_ upper bounds, making it more likely that a build will succeed.

All this information is in the manual, but I heard that the way it was written could be confusing, and the ReadTheDocs search doesn’t allow searching for infix operators like `^>=`. If you gained in understanding from this post, then there’s an **opportunity to volunteer here** : you have my full permission and encouragement to adapt any part of it to text in the manual for the `.cabal` file format and [contribute it upstream](https://github.com/haskell/cabal/pulls)! Just having learned something is the best time to write it down for others.

---

<div class="post-metadata">

**Author:** ![hasufell](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/hasufell/32/1250_2.png) [@hasufell](https://discourse.haskell.org/u/hasufell)\
**Post date:** [July 10, 2023, 1:04pm UTC](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938/2 "2023-07-10T13:04:17Z")

</div>

> [@david-christiansen](#):
>
> One of the PVP’s requirements is that packages have upper bounds

Hmm, I think I’m going to suggest to purge this requirement from PVP, especially since it knows nothing about the caret operator.

This seems like a non-sensible requirement for people testing their packages in a rolling-release fashion.

> [@david-christiansen](#):
>
> ```haskell
> allow-newer: ^somelib
> 
> ```

This is also a thing:

```haskell
allow-newer: ^all

```

[https://cabal.readthedocs.io/en/stable/cabal-project.html#cfg-field-allow-newer](https://cabal.readthedocs.io/en/stable/cabal-project.html#cfg-field-allow-newer)

---

<div class="post-metadata">

**Author:** ![bradrn](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/bradrn/32/264_2.png) [@bradrn](https://discourse.haskell.org/u/bradrn)\
**Post date:** [July 10, 2023, 1:52pm UTC](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938/3 "2023-07-10T13:52:46Z")

</div>

> [@hasufell](#):
>
> > [@david-christiansen](#):
> >
> > One of the PVP’s requirements is that packages have upper bounds
> 
> Hmm, I think I’m going to suggest to purge this requirement from PVP

Why? It seems like a fairly reasonable requirement to have.

---

<div class="post-metadata">

**Author:** ![hasufell](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/hasufell/32/1250_2.png) [@hasufell](https://discourse.haskell.org/u/hasufell)\
**Post date:** [July 10, 2023, 5:46pm UTC](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938/4 "2023-07-10T17:46:47Z")

</div>

It’s something reasonable to suggest, but it’s an unreasonable requirement.

A user might build their package every day against latest hackage, get notification of build failures and fix them the same day.

That’s a possible workflow. Something that’s even possible to implement holistically for hackage… if we allowed ourselves to have visions for this platform again.

Can the caret operator help here? Yes, but it still is a different signal and a different strategy. I believe both are valid (no upper bound vs `^>=` upper bound).

---

<div class="post-metadata">

**Author:** ![andreasabel](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/andreasabel/32/1764_2.png) [@andreasabel](https://discourse.haskell.org/u/andreasabel)\
**Post date:** [July 10, 2023, 6:47pm UTC](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938/5 "2023-07-10T18:47:42Z")

</div>

> [@david-christiansen](#):
>
> This specification of upper bounds has a key limitation: there’s no way to tell the difference between “2.5 doesn’t exist yet, so we’d better protect our users for when it comes out” and “I just tested with 2.5, and they changed that thing I depend on in such a way that I can’t work with both 2.4.x and 2.5.x at the same time”. Let’s call these two scenarios “conservative” and “definite” upper bounds. Without knowing the difference, build tools have to treat all upper bounds as if they are definite to avoid doing the wrong thing.

Exactly! We need _soft_ upper bounds (“conservative” — I have no evidence it works with larger versions) and _hard_ upper bounds (“definite” – I have evidence it does not work with larger versions).  
However, I think the caret operator is the wrong solution, since it ties in a lower bound, muddling the clear concepts. Rather, we should have a new operator for just soft upper bounds, like `<? 2.5`. These soft upper bounds can then ignored by tooling to test relaxation of upper bounds.

---

<div class="post-metadata">

**Author:** ![tomjaguarpaw](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tomjaguarpaw/32/1230_2.png) [@tomjaguarpaw](https://discourse.haskell.org/u/tomjaguarpaw)\
**Post date:** [July 10, 2023, 7:37pm UTC](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938/6 "2023-07-10T19:37:18Z")

</div>

Yes, that seems like a natural and straightforward approach. I always found `^>=` baffling, and can never remember what it means for longer than 5 minutes after the most recent time someone explained it to me.

---

<div class="post-metadata">

**Author:** ![mpilgrem](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/mpilgrem/32/2529_2.png) [@mpilgrem](https://discourse.haskell.org/u/mpilgrem)\
**Post date:** [July 10, 2023, 8:00pm UTC](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938/7 "2023-07-10T20:00:01Z")

</div>

The PVP states:

> When publishing a Cabal package, you SHALL ensure that your dependencies in the build-depends field are accurate. This means specifying not only lower bounds, but also upper bounds on every dependency.
> 
> At some point in the future, Hackage may refuse to accept packages that do not follow this convention. The aim is that before this happens, we will put in place tool support that makes it easier to follow the convention and less painful when dependencies are updated.

However, I think this is something `Distribution.PackageDescription.Check.checkPackage` does not warn about (except for the `base` package and the `library` stanza).

---

<div class="post-metadata">

**Author:** ![glguy](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/glguy/32/3359_2.png) [@glguy](https://discourse.haskell.org/u/glguy)\
**Post date:** [July 10, 2023, 11:21pm UTC](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938/8 "2023-07-10T23:21:05Z")

</div>

For this strategy to work, wouldn’t someone have to build every released version of their package at this daily cadence to ensure that that released version, which might get selected by some build plan, wouldn’t be the one to break due to failure to set upper bounds?

---

<div class="post-metadata">

**Author:** ![Vlix](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/vlix/32/1551_2.png) [@Vlix](https://discourse.haskell.org/u/Vlix)\
**Post date:** [July 11, 2023, 12:01am UTC](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938/9 "2023-07-11T00:01:12Z")

</div>

Oh, I’ve never known about what `^>=` actually does 😅

This is good to know, definitely. I’ll adjust my package dependencies accordingly 🤔

---

<div class="post-metadata">

**Author:** ![sclv](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/sclv/32/71_2.png) [@sclv](https://discourse.haskell.org/u/sclv)\
**Post date:** [July 11, 2023, 1:16am UTC](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938/10 "2023-07-11T01:16:04Z")

</div>

I very much support a soft upper bounds operator, not least because it will finally let us compose ^\>= 1.1 && ^\>= 1.2 into a single interval 🙂

For consistency’s sake, tho it may confuse some people, I’d be open to `<^` instead of `<?`.

---

<div class="post-metadata">

**Author:** ![waivio](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/waivio/32/1354_2.png) [@waivio](https://discourse.haskell.org/u/waivio)\
**Post date:** [July 11, 2023, 4:54am UTC](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938/11 "2023-07-11T04:54:56Z")

</div>

As I recall from the hubbub years ago about `^>=` is that the maintainer would declare the lower bound then some other Hackage process would test each version of the dependency (in some sort of matrix build) and automatically set the upper bound when breakage would occur.

---

<div class="post-metadata">

**Author:** ![f-a](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/f-a/32/2740_2.png) [@f-a](https://discourse.haskell.org/u/f-a)\
**Post date:** [July 11, 2023, 5:46am UTC](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938/12 "2023-07-11T05:46:12Z")

</div>

> [@mpilgrem](#):
>
> However, I think this is something `Distribution.PackageDescription.Check.checkPackage` does not warn about (except for the `base` package and the `library` stanza).

It already does warn on missing upper bounds for all dependencies on `master`.

---

<div class="post-metadata">

**Author:** ![chreekat](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/chreekat/32/2669_2.png) [@chreekat](https://discourse.haskell.org/u/chreekat)\
**Post date:** [July 11, 2023, 5:56am UTC](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938/13 "2023-07-11T05:56:05Z")

</div>

> [@andreasabel](#):
>
> However, I think the caret operator is the wrong solution, since it ties in a lower bound, muddling the clear concepts. Rather, we should have a new operator for just soft upper bounds, like `<? 2.5`. These soft upper bounds can then ignored by tooling to test relaxation of upper bounds.

I can only speculate that the rationale was “`^>= 0.4` is shorter and easier to write than `>= 0.4 && <? 0.5`”, but the latter sure seems better from a sense-making perspective.

What about conservative lower bounds? “`>=? 0.4 && <? 0.5`” makes sense, but I’m not even sure how I’d do it with carets.

---

<div class="post-metadata">

**Author:** ![mpilgrem](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/mpilgrem/32/2529_2.png) [@mpilgrem](https://discourse.haskell.org/u/mpilgrem)\
**Post date:** [July 11, 2023, 7:52am UTC](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938/14 "2023-07-11T07:52:24Z")

</div>

May I ask what is meant by "all dependencies on `master`"? Stack’s `sdist` command makes use of `checkPackage`, and, in simple tests, I could not provoke it into warning about missing upper bounds (except for `base`). (EDIT: If that is a bug in Stack, I’ll raise an issue and see if I can fix it - but I can’t see that Stack filters out any of the warnings it receives, for example.)

---

<div class="post-metadata">

**Author:** ![f-a](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/f-a/32/2740_2.png) [@f-a](https://discourse.haskell.org/u/f-a)\
**Post date:** [July 11, 2023, 8:19am UTC](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938/15 "2023-07-11T08:19:09Z")

</div>

Sorry, I was not clear.

I meant: on Cabal head, `cabal check` (and so, `checkPackage`) will check for all dependencies upper bounds (exceptions for benchmarks, tests). This feature was introduced in [#8361](https://github.com/haskell/cabal/pull/8361).

Users will find it in `cabal-install`/`Cabal` from version `3.10.1.0`.

Since [warings were typed](https://github.com/haskell/cabal/pull/8269), third party tools can easily filter what they are not interested in.

---

<div class="post-metadata">

**Author:** ![david-christiansen](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/david-christiansen/32/2404_2.png) [@david-christiansen](https://discourse.haskell.org/u/david-christiansen)\
**Post date:** [July 11, 2023, 9:03am UTC](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938/17 "2023-07-11T09:03:10Z")

</div>

> [@Vlix](#):
>
> Oh, I’ve never known about what `^>=` actually does 😅
> 
> This is good to know, definitely. I’ll adjust my package dependencies accordingly 🤔

Would you be interested in improving the manual so that it would convey this to you accurately? The text as written made immediate sense to me, but this is not a universal experience, so it would be good to make it more accessible. As someone who just learned it, you’re perfectly positioned to update the docs!

---

<div class="post-metadata">

**Author:** ![hasufell](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/hasufell/32/1250_2.png) [@hasufell](https://discourse.haskell.org/u/hasufell)\
**Post date:** [July 11, 2023, 9:46am UTC](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938/18 "2023-07-11T09:46:09Z")

</div>

> [@maxigit](#):
>
> Is the `^>=` not redundant with the principle of PVP itself ?

`>=2.5` will cause a build failure by **default** if your codebase is not working with 2.6. `^>=2.5` will **not** cause a build failure by default, unless a user has set `allow-newer: ^all` or similar.

So these are quite different in practice.

---

<div class="post-metadata">

**Author:** ![hasufell](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/hasufell/32/1250_2.png) [@hasufell](https://discourse.haskell.org/u/hasufell)\
**Post date:** [July 11, 2023, 9:57am UTC](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938/20 "2023-07-11T09:57:24Z")

</div>

Yeah, that might be a good indication that it doesn’t belong in the PVP spec after all.

---

<div class="post-metadata">

**Author:** ![chreekat](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/chreekat/32/2669_2.png) [@chreekat](https://discourse.haskell.org/u/chreekat)\
**Post date:** [July 11, 2023, 10:17am UTC](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938/21 "2023-07-11T10:17:22Z")

</div>

> [@maxigit](#):
>
> It’s only because tools decide to treat them differently even their semantic is quite the same IMHO.

Their semantics are definitely different. The whole reason tools can treat them differently is _because_ their semantics are different.

But the fact that we’re still having this debate on a topic that was ideally about clearing up their purpose is not a good sign of how easy they are to work with.

---

<div class="post-metadata">

**Author:** ![chreekat](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/chreekat/32/2669_2.png) [@chreekat](https://discourse.haskell.org/u/chreekat)\
**Post date:** [July 11, 2023, 10:30am UTC](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938/23 "2023-07-11T10:30:48Z")

</div>

> [@maxigit](#):
>
> (because `>=2.5` can’t actually mean what it is supposed to mean),

Oh, I think I misunderstand what you’re talking about.

`^>=` is a lower bound, identical to `>=`.

But it is _also_ an _upper_ bound. A speculative one. Or “conservative”, if you prefer. `^>= 3.2` means “I don’t know if this works with 3.3 or not.”

It’s the _upper bound_ nature of `^>=` that I’ve been talking about. It’s different than `< 3.3`, which used to mean “I know this doesn’t work with 3.3 _ **OR** _ I have no idea if this works with 3.3”, and now… well… now it _could_ be restricted to mean “I definitely know this doesn’t work with 3.3”. Assuming everyone adopts the caret bound.

[Next page](https://discourse.haskell.org/t/the-operator-in-cabal-files/6938.md?page=2)
