Types and parsers for software version numbers.

Version on this page:3.1.1
LTS Haskell 22.29:6.0.7
Stackage Nightly 2024-07-17:6.0.7
Latest on Hackage:6.0.7

See all snapshots versions appears in

BSD-3-Clause licensed by Colin Woodbury
Maintained by [email protected]
This version can be pinned in stack with:versions-3.1.1@sha256:ae9d91d2bb1744ccd4bfb154fd51c66d935a7b1f66d8df3e7bd71112559347d4,2248

Module documentation for 3.1.1


Build Status 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, parseV 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 & svPatch %~ (+ 1)

Or, something more involved:

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

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

-- | Get all major versions of legally parsed SemVers.
majors :: [Text] -> [Int]
majors vs = vs ^.. each . _SemVer . svMajor

Note that _SemVer only attempts to parse as true Semantic Versioning. If the package versions you’re parsing don’t agree to a standard, you can achieve a similar result via:

-- | Get all major versions of potentially parsed SemVers.
majors :: [Text] -> [Int]
majors vs = vs ^.. each . _Versioning . _Ideal . svMajor

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

incPatch :: Text -> Text
incPatch s = s & _SemVer . svPatch %~ (+ 1)

> incPatch "1.2.3"




  • 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)