Copyright | 2021 Thomas Bidne |
---|---|
License | BSD-3-Clause |
Stability | experimental |
Safe Haskell | None |
Language | Haskell2010 |
Data.Version.Package
Description
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.
The doctest examples use -XOverloadedLists
.
Since: 0.1.0.0
Synopsis
- newtype PackageVersion = MkPackageVersion {}
- mkPackageVersion :: [Int] -> Either ValidationError PackageVersion
- mkPackageVersionTH :: [Int] -> Code Q PackageVersion
- unsafePackageVersion :: HasCallStack => [Int] -> PackageVersion
- fromVersion :: Version -> Either ValidationError PackageVersion
- fromString :: String -> Either ReadStringError PackageVersion
- fromText :: Text -> Either ReadStringError PackageVersion
- 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
- data ReadStringError
- data ReadFileError
Type
newtype PackageVersion Source #
PackageVersion
represents PVP version numbers. It is similar to Data.Version's Version
except:
PackageVersion
has noversionTags
.We enforce PVP invariants i.e.
- Tags must have at least one component.
- All components >= 0.
- 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,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 NonEmpty
(or Word
String
) representation.
Examples
>>>
MkPackageVersion [0,0,0,0] == MkPackageVersion [0,0,0]
True
>>>
MkPackageVersion [4,0,0] > MkPackageVersion [1,2,0,0]
True
>>>
MkPackageVersion [5,6,0] <> MkPackageVersion [9,0,0]
MkPackageVersion {unPackageVersion = 9 :| [0,0]}
>>>
MkPackageVersion [0,9] <> MkPackageVersion [0,9,0,0]
MkPackageVersion {unPackageVersion = 0 :| [9]}
Since: 0.1.0.0
Constructors
MkPackageVersion | |
Fields
|
Instances
Creation
mkPackageVersion :: [Int] -> Either ValidationError PackageVersion Source #
Constructs a PackageVersion
from an Int
list. The list must be non-empty to match PVP's minimal A. Furthermore, all digits must be non-negative.
Examples
>>>
mkPackageVersion [1,2]
Right (MkPackageVersion {unPackageVersion = 1 :| [2]})
>>>
mkPackageVersion [2,87,7,1]
Right (MkPackageVersion {unPackageVersion = 2 :| [87,7,1]})
>>>
mkPackageVersion [1,2,-3,-4,5]
Left (ValidationErrorNegative (-3))
>>>
mkPackageVersion [3]
Right (MkPackageVersion {unPackageVersion = 3 :| []})
>>>
mkPackageVersion []
Left ValidationErrorEmpty
Since: 0.1.0.0
mkPackageVersionTH :: [Int] -> Code Q PackageVersion Source #
Safely constructs a PackageVersion
at compile-time. If you know that your input satisfies both invariants (non-empty and non-negative) at compile-time, consider using the MkPackageVersion
constructor directly.
Examples
>>>
$$(mkPackageVersionTH [2,4,0])
MkPackageVersion {unPackageVersion = 2 :| [4,0]}
Since: 0.1.0.0
unsafePackageVersion :: HasCallStack => [Int] -> PackageVersion Source #
Unsafe version of mkPackageVersion
, intended to be used with known constants. Maybe you should use mkPackageVersionTH
or MkPackageVersion
?
WARNING: This function is not total. Exercise restraint!
Examples
>>>
unsafePackageVersion [1,2,3]
MkPackageVersion {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 (MkPackageVersion {unPackageVersion = 2 :| [13,0]})
>>>
fromVersion (Version [] [])
Left ValidationErrorEmpty
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 (MkPackageVersion {unPackageVersion = 1 :| [4,27,3]})
>>>
fromString ""
Left (ReadStringErrorParse "Prelude.read: no parse")
>>>
fromString "1.a.2"
Left (ReadStringErrorParse "Prelude.read: no parse")
>>>
fromString ".1.2"
Left (ReadStringErrorParse "Prelude.read: no parse")
>>>
fromString "1.2."
Left (ReadStringErrorParse "Prelude.read: no parse")
>>>
fromString "-3.1.2"
Left (ReadStringErrorValidate (ValidationErrorNegative (-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 (MkPackageVersion {unPackageVersion = 1 :| [4,27,3]})
>>>
fromText ""
Left (ReadStringErrorParse "Prelude.read: no parse")
>>>
fromText "1.a.2"
Left (ReadStringErrorParse "Prelude.read: no parse")
>>>
fromText ".1.2"
Left (ReadStringErrorParse "Prelude.read: no parse")
>>>
fromText "1.2."
Left (ReadStringErrorParse "Prelude.read: no parse")
>>>
fromText ""
Left (ReadStringErrorParse "Prelude.read: no parse")
>>>
fromText "-3.1.2"
Left (ReadStringErrorValidate (ValidationErrorNegative (-3)))
Since: 0.1.0.0
Elimination
toVersion :: PackageVersion -> Version Source #
Creates a Version
with empty versionTags
from PackageVersion
.
Examples
>>>
toVersion (MkPackageVersion [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 (MkPackageVersion [2,7,10,0])
"2.7.10.0"
Since: 0.1.0.0
toText :: PackageVersion -> Text Source #
Displays PackageVersion
in Text
format.
Examples
>>>
toText (MkPackageVersion [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")
MkPackageVersion {unPackageVersion = 0 :| [4,1]}
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.4.1"
>>>
$$(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.4.1"
>>>
$$(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"
MkPackageVersion {unPackageVersion = 0 :| [4,1]}
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.4.1"
>>>
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.4.1"
>>>
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 (MkPackageVersion {unPackageVersion = 0 :| [4,1]})
Since: 0.1.0.0
Errors
data ValidationError Source #
Errors that can occur when validating PVP version numbers.
Since: 0.1.0.0
Constructors
ValidationErrorEmpty | PVP version number cannot be empty. Since: 0.3 |
ValidationErrorNegative Int | PVP version numbers cannot be negative. Since: 0.2 |
Instances
Exception ValidationError Source # | Since: 0.1.0.0 | ||||
Defined in Data.Version.Package.Internal Methods toException :: ValidationError -> SomeException # | |||||
Generic ValidationError Source # | |||||
Defined in Data.Version.Package.Internal Associated Types
Methods from :: ValidationError -> Rep ValidationError x # to :: Rep ValidationError x -> ValidationError # | |||||
Show ValidationError Source # | Since: 0.1.0.0 | ||||
Defined in Data.Version.Package.Internal Methods showsPrec :: Int -> ValidationError -> ShowS # show :: ValidationError -> String # showList :: [ValidationError] -> ShowS # | |||||
NFData ValidationError Source # | Since: 0.2 | ||||
Defined in Data.Version.Package.Internal Methods rnf :: ValidationError -> () # | |||||
Eq ValidationError Source # | Since: 0.1.0.0 | ||||
Defined in Data.Version.Package.Internal Methods (==) :: ValidationError -> ValidationError -> Bool # (/=) :: ValidationError -> ValidationError -> Bool # | |||||
type Rep ValidationError Source # | Since: 0.1.0.0 | ||||
Defined in Data.Version.Package.Internal type Rep ValidationError = D1 ('MetaData "ValidationError" "Data.Version.Package.Internal" "package-version-0.4.1-sK2rTwuAqKB53YXat6AW4" 'False) (C1 ('MetaCons "ValidationErrorEmpty" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "ValidationErrorNegative" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Int))) |
data ReadStringError Source #
Errors that can occur when reading PVP version numbers.
Since: 0.1.0.0
Constructors
ReadStringErrorParse String | Error when parsing a string. Since: 0.2 |
ReadStringErrorValidate ValidationError | Validation error. Since: 0.2 |
Instances
Exception ReadStringError Source # | Since: 0.1.0.0 | ||||
Defined in Data.Version.Package.Internal Methods toException :: ReadStringError -> SomeException # | |||||
Generic ReadStringError Source # | |||||
Defined in Data.Version.Package.Internal Associated Types
Methods from :: ReadStringError -> Rep ReadStringError x # to :: Rep ReadStringError x -> ReadStringError # | |||||
Show ReadStringError Source # | Since: 0.1.0.0 | ||||
Defined in Data.Version.Package.Internal Methods showsPrec :: Int -> ReadStringError -> ShowS # show :: ReadStringError -> String # showList :: [ReadStringError] -> ShowS # | |||||
NFData ReadStringError Source # | Since: 0.2 | ||||
Defined in Data.Version.Package.Internal Methods rnf :: ReadStringError -> () # | |||||
Eq ReadStringError Source # | Since: 0.1.0.0 | ||||
Defined in Data.Version.Package.Internal Methods (==) :: ReadStringError -> ReadStringError -> Bool # (/=) :: ReadStringError -> ReadStringError -> Bool # | |||||
type Rep ReadStringError Source # | Since: 0.1.0.0 | ||||
Defined in Data.Version.Package.Internal type Rep ReadStringError = D1 ('MetaData "ReadStringError" "Data.Version.Package.Internal" "package-version-0.4.1-sK2rTwuAqKB53YXat6AW4" 'False) (C1 ('MetaCons "ReadStringErrorParse" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 String)) :+: C1 ('MetaCons "ReadStringErrorValidate" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 ValidationError))) |
data ReadFileError Source #
Errors that can occur when reading PVP version numbers from a file.
Since: 0.1.0.0
Constructors
ReadFileErrorGeneral String | General error when reading a file. Since: 0.2 |
ReadFileErrorVersionNotFound FilePath | Error for missing version. Since: 0.2 |
ReadFileErrorReadString ReadStringError | Read/Validation error. Since: 0.2 |
Instances
Exception ReadFileError Source # | Since: 0.1.0.0 | ||||
Defined in Data.Version.Package.Internal Methods toException :: ReadFileError -> SomeException # fromException :: SomeException -> Maybe ReadFileError # displayException :: ReadFileError -> String # | |||||
Generic ReadFileError Source # | |||||
Defined in Data.Version.Package.Internal Associated Types
| |||||
Show ReadFileError Source # | Since: 0.1.0.0 | ||||
Defined in Data.Version.Package.Internal Methods showsPrec :: Int -> ReadFileError -> ShowS # show :: ReadFileError -> String # showList :: [ReadFileError] -> ShowS # | |||||
NFData ReadFileError Source # | Since: 0.2 | ||||
Defined in Data.Version.Package.Internal Methods rnf :: ReadFileError -> () # | |||||
Eq ReadFileError Source # | Since: 0.1.0.0 | ||||
Defined in Data.Version.Package.Internal Methods (==) :: ReadFileError -> ReadFileError -> Bool # (/=) :: ReadFileError -> ReadFileError -> Bool # | |||||
type Rep ReadFileError Source # | Since: 0.1.0.0 | ||||
Defined in Data.Version.Package.Internal type Rep ReadFileError = D1 ('MetaData "ReadFileError" "Data.Version.Package.Internal" "package-version-0.4.1-sK2rTwuAqKB53YXat6AW4" 'False) (C1 ('MetaCons "ReadFileErrorGeneral" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 String)) :+: (C1 ('MetaCons "ReadFileErrorVersionNotFound" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 FilePath)) :+: C1 ('MetaCons "ReadFileErrorReadString" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 ReadStringError)))) |