Copyright | 2021 Thomas Bidne |
---|---|
License | BSD-3-Clause |
Stability | experimental |
Safe Haskell | Safe-Inferred |
Language | Haskell2010 |
This module provides functionality for reading a package's version
at compile-time, along with a type representing PVP version numbers.
If only the former is of interest then see packageVersionStringTH
, as
this is likely the most useful function.
Since: 0.1.0.0
Synopsis
- data PackageVersion where
- pattern MkPackageVersion :: [Int] -> PackageVersion
- mkPackageVersion :: [Int] -> Either ValidationError PackageVersion
- mkPackageVersionTH :: [Int] -> Code Q PackageVersion
- unsafePackageVersion :: [Int] -> PackageVersion
- fromVersion :: Version -> Either ValidationError PackageVersion
- fromString :: String -> Either ReadStringError PackageVersion
- fromText :: Text -> Either ReadStringError PackageVersion
- unPackageVersion :: PackageVersion -> [Int]
- toVersion :: PackageVersion -> Version
- toString :: PackageVersion -> String
- toText :: PackageVersion -> Text
- packageVersionTH :: FilePath -> Code Q PackageVersion
- packageVersionStringTH :: FilePath -> Code Q String
- packageVersionTextTH :: FilePath -> Code Q Text
- packageVersionThrowIO :: FilePath -> IO PackageVersion
- packageVersionStringIO :: FilePath -> IO String
- packageVersionTextIO :: FilePath -> IO Text
- packageVersionEitherIO :: FilePath -> IO (Either ReadFileError PackageVersion)
- data ValidationError
- = VTooShortErr [Int]
- | VNegativeErr Int
- data ReadStringError
- data ReadFileError
Type
data PackageVersion where Source #
PackageVersion
represents PVP version
numbers. It is similar to Data.Version's Version
(i.e. wraps a
[
) except:Int
]
PackageVersion
has noversionTags
.- We enforce PVP's "tags must be at least A.B" invariant via the smart-constructor pattern.
- Trailing zeroes are ignored in
Eq
,Ord
,Semigroup
, andMonoid
.
That is, we declare an equivalence class up to trailing zeroes.
In particular, the Monoid
identity is
[0] = { [0,0], [0,0,0], ... }
and its Semigroup
instance takes the greatest version (based on Ord
).
Note: Because we export the underlying list in various ways,
(e.g. show
), Eq
's extensionality law,
x == y ==> f x == f y
can be broken. Take care that you do not rely on this law if you are
using its underlying [
(or Int
]String
) representation.
Examples
>>>
UnsafePackageVersion [0,0,0,0] == UnsafePackageVersion [0,0,0]
True
>>>
UnsafePackageVersion [4,0,0] > UnsafePackageVersion [1,2,0,0]
True
>>>
UnsafePackageVersion [5,6,0] <> UnsafePackageVersion [9,0,0]
UnsafePackageVersion {unPackageVersion = [9,0,0]}
>>>
UnsafePackageVersion [0,9] <> UnsafePackageVersion [0,9,0,0]
UnsafePackageVersion {unPackageVersion = [0,9]}
>>>
TR.readEither @PackageVersion "UnsafePackageVersion {unPackageVersion = [3,2,1]}"
Right (UnsafePackageVersion {unPackageVersion = [3,2,1]})
>>>
TR.readEither @PackageVersion "UnsafePackageVersion {unPackageVersion = [3]}"
Left "Prelude.read: no parse"
Since: 0.1.0.0
pattern MkPackageVersion :: [Int] -> PackageVersion | Since: 0.1.0.0 |
Instances
Creation
mkPackageVersion :: [Int] -> Either ValidationError PackageVersion Source #
Smart constructor for PackageVersion
. The length of the list must be
> 1 to match PVP's minimal A.B. Furthermore, all digits must be non-negative.
Examples
>>>
mkPackageVersion [1,2]
Right (UnsafePackageVersion {unPackageVersion = [1,2]})
>>>
mkPackageVersion [2,87,7,1]
Right (UnsafePackageVersion {unPackageVersion = [2,87,7,1]})
>>>
mkPackageVersion [1,2,-3,-4,5]
Left (VNegativeErr (-3))
>>>
mkPackageVersion [3]
Left (VTooShortErr [3])
>>>
mkPackageVersion []
Left (VTooShortErr [])
Since: 0.1.0.0
mkPackageVersionTH :: [Int] -> Code Q PackageVersion Source #
Safely constructs a PackageVersion
at compile-time.
Examples
>>>
$$(mkPackageVersionTH [2,4,0])
UnsafePackageVersion {unPackageVersion = [2,4,0]}
Since: 0.1.0.0
unsafePackageVersion :: [Int] -> PackageVersion Source #
Unsafe version of mkPackageVersion
, intended to be used with
known constants. Maybe you should use mkPackageVersionTH
?
WARNING: This function is not total. Exercise restraint!
Examples
>>>
unsafePackageVersion [1,2,3]
UnsafePackageVersion {unPackageVersion = [1,2,3]}
Since: 0.1.0.0
fromVersion :: Version -> Either ValidationError PackageVersion Source #
Creates a PackageVersion
from Version
.
Note: Because PackageVersion
does not have a versionTags
, fromVersion
is not injective even on "well-formed" Version
s (i.e. non-negative and length > 1).
That is,
is not an isomorphism.toVersion
. fromVersion
Examples
>>>
fromVersion (Version [2,13,0] ["alpha"])
Right (UnsafePackageVersion {unPackageVersion = [2,13,0]})
>>>
fromVersion (Version [] [])
Left (VTooShortErr [])
Since: 0.1.0.0
fromString :: String -> Either ReadStringError PackageVersion Source #
Attempts to read a String
into a PackageVersion
. Leading and/or
trailing dots will result in an error, as will the empty string.
Examples
>>>
fromString "1.4.27.3"
Right (UnsafePackageVersion {unPackageVersion = [1,4,27,3]})
>>>
fromString ""
Left (RsReadStrErr "Prelude.read: no parse")
>>>
fromString "1.a.2"
Left (RsReadStrErr "Prelude.read: no parse")
>>>
fromString ".1.2"
Left (RsReadStrErr "Prelude.read: no parse")
>>>
fromString "1.2."
Left (RsReadStrErr "Prelude.read: no parse")
>>>
fromString "1"
Left (RsValidateErr (VTooShortErr [1]))
>>>
fromString "-3.1.2"
Left (RsValidateErr (VNegativeErr (-3)))
Since: 0.1.0.0
fromText :: Text -> Either ReadStringError PackageVersion Source #
Attempts to read a Text
into a PackageVersion
. Leading and/or
trailing dots will result in an error, as will the empty string.
Examples
>>>
fromText "1.4.27.3"
Right (UnsafePackageVersion {unPackageVersion = [1,4,27,3]})
>>>
fromText ""
Left (RsReadStrErr "Prelude.read: no parse")
>>>
fromText "1.a.2"
Left (RsReadStrErr "Prelude.read: no parse")
>>>
fromText ".1.2"
Left (RsReadStrErr "Prelude.read: no parse")
>>>
fromText "1.2."
Left (RsReadStrErr "Prelude.read: no parse")
>>>
fromText "1"
Left (RsValidateErr (VTooShortErr [1]))
>>>
fromText "-3.1.2"
Left (RsValidateErr (VNegativeErr (-3)))
Since: 0.1.0.0
Elimination
unPackageVersion :: PackageVersion -> [Int] Source #
Since: 0.1.0.0
toVersion :: PackageVersion -> Version Source #
Creates a Version
with empty versionTags
from PackageVersion
.
Examples
>>>
toVersion (UnsafePackageVersion [3,2,0])
Version {versionBranch = [3,2,0], versionTags = []}
Since: 0.1.0.0
toString :: PackageVersion -> String Source #
Displays PackageVersion
in String
format.
Examples
>>>
toString (UnsafePackageVersion [2,7,10,0])
"2.7.10.0"
Since: 0.1.0.0
toText :: PackageVersion -> Text Source #
Displays PackageVersion
in Text
format.
Examples
>>>
toText (UnsafePackageVersion [2,7,10,0])
"2.7.10.0"
Since: 0.1.0.0
Reading Cabal Files
TemplateHaskell
These functions allow for reading a cabal's version at compile-time. If
the intention is to simply read the value so it can be printed during
runtime (e.g. for an executable's --version
flag), then
packageVersionStringTH
(or packageVersionTextTH
) is the best choice,
as any errors encountered will not prevent compilation.
packageVersionTH :: FilePath -> Code Q PackageVersion Source #
TemplateHaskell for reading the cabal file's version at compile-time. Errors encountered will be returned as compilation errors.
Examples
>>>
$$(packageVersionTH "package-version.cabal")
UnsafePackageVersion {unPackageVersion = [0,1,0,0]}
Since: 0.1.0.0
packageVersionStringTH :: FilePath -> Code Q String Source #
Version of packageVersionTH
that returns a String
representation of
PackageVersion
at compile-time. Returns "UNKNOWN"
if any errors are
encountered.
Examples
>>>
$$(packageVersionStringTH "package-version.cabal")
"0.1.0.0"
>>>
$$(packageVersionStringTH "not-found.cabal")
"UNKNOWN"
Since: 0.1.0.0
packageVersionTextTH :: FilePath -> Code Q Text Source #
Version of packageVersionTH
that returns a Text
representation of
PackageVersion
at compile-time. Returns "UNKNOWN"
if any errors are
encountered.
Examples
>>>
$$(packageVersionTextTH "package-version.cabal")
"0.1.0.0"
>>>
$$(packageVersionTextTH "not-found.cabal")
"UNKNOWN"
Since: 0.1.0.0
IO
packageVersionThrowIO :: FilePath -> IO PackageVersion Source #
Version of packageVersionEitherIO
that throws an
Exception
if any errors are encountered.
Examples
>>>
packageVersionThrowIO "package-version.cabal"
UnsafePackageVersion {unPackageVersion = [0,1,0,0]}
Since: 0.1.0.0
packageVersionStringIO :: FilePath -> IO String Source #
Version of packageVersionEitherIO
that returns a String
representation of
PackageVersion
at runtime. Returns "UNKNOWN"
if any errors are
encountered.
Examples
>>>
packageVersionStringIO "package-version.cabal"
"0.1.0.0"
>>>
packageVersionStringIO "not-found.cabal"
"UNKNOWN"
Since: 0.1.0.0
packageVersionTextIO :: FilePath -> IO Text Source #
Version of packageVersionEitherIO
that returns a Text
representation of
PackageVersion
at runtime. Returns "UNKNOWN"
if any errors are
encountered.
Examples
>>>
packageVersionTextIO "package-version.cabal"
"0.1.0.0"
>>>
packageVersionTextIO "not-found.cabal"
"UNKNOWN"
Since: 0.1.0.0
packageVersionEitherIO :: FilePath -> IO (Either ReadFileError PackageVersion) Source #
Reads the cabal-file's version.
Examples
>>>
packageVersionEitherIO "package-version.cabal"
Right (UnsafePackageVersion {unPackageVersion = [0,1,0,0]})
Since: 0.1.0.0
Errors
data ValidationError Source #
Errors that can occur when validating PVP version numbers.
Since: 0.1.0.0
VTooShortErr [Int] | PVP version numbers must be at least A.B Since: 0.1.0.0 |
VNegativeErr Int | PVP version numbers cannot be negative. Since: 0.1.0.0 |
Instances
data ReadStringError Source #
Errors that can occur when reading PVP version numbers.
Since: 0.1.0.0
RsReadStrErr String | Error when reading a string. Since: 0.1.0.0 |
RsValidateErr ValidationError | Validation error. Since: 0.1.0.0 |
Instances
data ReadFileError Source #
Errors that can occur when reading PVP version numbers from a file.
Since: 0.1.0.0
RfFileNotFoundErr String | Error for missing file. Since: 0.1.0.0 |
RfVersionNotFoundErr FilePath | Error for missing version. Since: 0.1.0.0 |
RfReadValidateErr ReadStringError | Read/Validation error. Since: 0.1.0.0 |