BSD-3-Clause licensed by Colin Woodbury
Maintained by [email protected]
This version can be pinned in stack with:versions-6.0.7@sha256:51bd8412c1e00842e43e2e23d1490a0219649d0364124ced78ff32b1a80aa096,1993

Module documentation for 6.0.7


Hackage Stackage Nightly Stackage LTS

A Haskell library for parsing and comparing software version numbers.


We like to give version numbers to our software in a myriad of ways. Some ways follow strict guidelines for incrementing and comparison. Some follow conventional wisdom and are generally self-consistent. Some are just plain asinine. This library provides a means of parsing and comparing any style of versioning, be it a nice Semantic Version like this:


…or a monstrosity like this:


Please switch to Semantic Versioning if you aren’t currently using it. It provides consistency in version incrementing and has the best constraints on comparisons.


In general, versioning is the function you want. It attempts to parse a given Text using the three individual parsers, semver, version and mess. If one fails, it tries the next. If you know you only want to parse one specific version type, use that parser directly (e.g. semver).

Lenses and Traversals

The parse result types have Lenses/Traversals for accessing their data fields. For instance, to increment the patch number of a parsed SemVer, you could:

incPatch :: SemVer -> SemVer
incPatch s = s & patch %~ (+ 1)

Or, something more involved:

-- | Get all major versions of legally parsed SemVers.
majors :: [Text] -> [Word]
majors vs = vs ^.. each . to semver . _Right . major

The to semver . _Right is clunky, so we provide some direct Text Traverals inspired by (micro) lens-aeson:

-- | Get the major version of any `Text` that has one.
majors :: [Text] -> [Word]
majors vs = vs ^.. each . major

We can also use these Text Traversals to increment versions, as above:

incPatch :: Text -> Text
incPatch s = s & patch %~ (+ 1)

> incPatch "1.2.3"


The largest number that can be parsed as part of a version is:

ghci> maxBound :: Word64

However, on 32-bit systems (or smaller), the maximum is their maxBound :: Word. A number larger than that, even if smaller than maxBound :: Word64, will yield a parse error.



6.0.7 (2024-06-03)


  • Bumped upper bound on base.

6.0.6 (2024-03-08)


  • Account for large numbers when parsing on 32-bit (or smaller) systems.

6.0.5 (2024-01-24)


  • Certain illegal versions were parsing as PVP.

6.0.4 (2023-12-29)


  • Bump dependencies to support GHC 9.8.

6.0.3 (2023-10-23)


  • Data instances for the various data types.
  • Simple conversion functions between the main version types.
  • Compile-time constructors via Template Haskell, like versioningQ.

6.0.2 (2023-10-12)


  • Lift instances for the various types, which allows parsing version numbers at compile time within Template Haskell quotes. Currently there is no exported function that supports this directly, but you could write one like:
-- | Parse a `Versioning` at compile time.
thVer :: Text -> Q Exp
thVer nm =
  case versioning nm of
    Left err -> fail (errorBundlePretty err)
    Right v  -> lift v


  • Due to the new dependency on template-haskell, GHC 8.8 is now the lowest supported compiler version.

6.0.1 (2023-05-08)


  • Restored the ability to compile with GHC versions earlier than 9.

6.0.0 (2023-04-29)

A number of type changes have been made to improve parsing and comparison logic. Doing so fixed several bugs and made the code cleaner overall.

If you’re just doing basic parsing and comparisons and not actually inspecting the types themselves, you shouldn’t notice a difference.


  • New types Release, Chunks, and Chunk.


  • Both SemVer and Version now contain a better-behaving Release type for their prerelease info.
  • Similarly, Version now also has a better-behaving Chunks type for its main version number sections.
  • The release traversal now yields a Maybe Release.
  • Versions with ~ in their metadata will now parse as a Mess. Example: 12.0.0-3ubuntu1~20.04.5


  • The various Semigroup instances. Adding version numbers together is a nonsensical operation and should never have been added in the first place.
  • The VChunk and VUnit types and their associated functions.


  • Leading zeroes are handled a little better in SemVer pre-release data.

5.0.5 (2023-03-23)


  • Bumped base bound to support GHC 9.6.

5.0.4 (2022-10-18)


  • Bumped base bound to support GHC 9.4.

5.0.3 (2022-02-25)


  • A bug in prettyVer that flipped the order of the preRel and meta fields.

5.0.2 (2022-01-21)


  • text-2.0 support.

5.0.1 (2021-12-08)


  • Support for GHC 9.2.


  • Remove redundant pattern match.

5.0.0 (2021-04-14)

This release brings versions in line with version 2.0.0 of the SemVer spec. The main addition to the spec is the allowance of hyphens in both the prerelease and metadata sections. As such, certain versions like 1.2.3+1-1 which previously would not parse as SemVer now do.

To accomodate this and other small spec updates, the SemVer and Version types have received breaking changes here.


  • Breaking: The _svMeta field of SemVer is now parsed as a dumber Maybe Text instead of [VChunk], due to metadata now being allowed to possess leading zeroes.
  • Breaking: Like the above, the _vMeta field of Version is now Maybe Text.
  • Breaking: The _vRel and _vMeta fields of Version have had their order flipped. Further, the prelease and meta sections are now expected in the same order as SemVer when parsing (prerel first, meta second). Version is thus now a quite similar to SemVer, except allowing letters in more permissive positions.
  • Breaking: The meta traversal has been altered to accomodate the metadata field changes.


  • Parsing certain legal SemVers specified in the spec.

4.0.3 (2021-02-23)


  • Support for GHC 9.

4.0.2 (2021-01-23)


  • A bug in zero parsing within SemVer prereleases. #42

4.0.1 (2020-10-22)


  • An infinite loop in Version comparison. aura#652

4.0.0 (2020-10-20)


  • Breaking: VChunk now cannot be empty.
  • Breaking: A Version now guarantees NonEmpty chunks.
  • Breaking: A Mess now guarantees NonEmpty chunks, and its structure has been significantly changed. Particularly, Mess values are now aware of the Int values they hold (when they do), as well as “revision” values of the pattern rXYZ.
  • Comparison of Version values is more memory efficient.


  • Version now has an extra field, _vMeta :: [VChunk] for capturing “metadata” like Semver. This prevents otherwise nice-looking versions from being demoted to Mess.
  • The MChunk type to accomodate the changes to Mess mentioned above.


  • Breaking: Version no longer has a Monoid instance.


  • "" no longer parses in any way. #32
  • Version strings with trailing whitespace no longer parse via versioning. #33
  • Particular edge cases involving Mess comparisons. aura#646
  • A particular edge case involving prereleases in Version comparisons. aura#586

3.5.4 (2020-05-12)


  • The functions isIdeal, isGeneral, and isComplex for Bool-based inspection of parse results.
  • messMajor, messMinor, messPatch, and messPatchChunk for improved introspection into Mess values.


  • Improved Mess comparison logic.


  • GHC 8.10 support.


  • Added a new PVP type and parsers.

  • GHC 8.8 compatibility.


  • Updated to megaparsec-7. Our ParsingError type alias has changed to match Megaparsec’s new error model, and errorBundlePretty is now exposed instead of the old parseErrorPretty.

  • Enhanced the whitespace handling in semver', version', and mess'.


  • Removed ParseV and surrounding machinery. Use versioning now instead of the parseV function.


  • GHC 8.4.1 compatibility.


  • New Semantic typeclass that provides Traversals for SemVer-like data out of all the version types. Text was also given an instance, so its much easier to manipulate directly:
λ "1.2.3" & minor %~ (+ 1)

Some Lenses and Traversals had their names changed or were removed entirely to accomodate this new typeclass.

  • SemVer and Version should never contain negative values, so their numeric components were changed from Int to Word.


  • Updated for megaparsec-6 and GHC 8.2.


  • Added instances for common typeclasses: Generic, NFData, and Hashable. This is to avoid having users define these instances themselves as orphans. If there are more instances you want added, please let me know. Data was left out on purpose.


  • Added support for epoch numbers in the Version type. These are numbers like the 1: in 1:2.3.4. These are used in Arch Linux in rare cases where packages change their versioning scheme, but need a reliable integer prefix to establish ordering. The Version type has been given a new field, _vEpoch :: Maybe Int, and a corresponding lens, vEpoch.


  • Expose internal parsers so that they could be used in other parser programs that parse version numbers in larger files.


  • Updated for megaparsec-5 and ghc-8


  • Switched to megaparsec to perform all parsing as Text
  • Support for legacy String removed
  • Added more Traversals and INLINE’d all Lenses/Traversals


  • Added Lenses and Traversals (no lens dependency)