prefix-units 0.2.0 → 0.3.0.1
raw patch · 5 files changed
+235/−120 lines, 5 filesdep +deepseqPVP ok
version bump matches the API change (PVP)
Dependencies added: deepseq
API changes (from Hackage documentation)
- Data.Prefix.Units: instance Data.Prefix.Units.RationalConvertible GHC.Integer.Type.Integer
+ Data.Prefix.Units: Quecto :: Unit
+ Data.Prefix.Units: Quetta :: Unit
+ Data.Prefix.Units: Ronna :: Unit
+ Data.Prefix.Units: Ronto :: Unit
+ Data.Prefix.Units: instance Data.Prefix.Units.RationalConvertible GHC.Num.Integer.Integer
- Data.Prefix.Units: formatValue :: (RationalConvertible a) => FormatMode -> a -> (a, Maybe Unit)
+ Data.Prefix.Units: formatValue :: RationalConvertible a => FormatMode -> a -> (a, Maybe Unit)
- Data.Prefix.Units: recommendedUnit :: (Real a) => FormatMode -> a -> Maybe Unit
+ Data.Prefix.Units: recommendedUnit :: Real a => FormatMode -> a -> Maybe Unit
Files
- CHANGES.md +34/−4
- Data/Prefix/Units.hs +126/−81
- README.md +4/−1
- prefix-units.cabal +45/−30
- tests/Properties.hs +26/−4
CHANGES.md view
@@ -1,5 +1,29 @@-Version 0.2.0+## Version 0.3.0.1 +*released Thu, 27 Apr 2023*++It turns out that even if `cabal check` shows no warnings, Hackage+doesn't accept packages with very old cabal version constraints. So+this release bumps that, which in turns makes `cabal check` actually+start to show warnings, so modernise the cabal file as a result.++There are no code changes compared to 0.3.0, so this is a no-op+release from the point of view of functionality.++## Version 0.3.0++*released Wed, 26 Apr 2023*++* Add the new quecto/ronto/ronna/quetta units. I didn't think I'd ever+ have to extend the list of units! Not sure entirely if these should+ be part of the parseKMGT function, since they're high enough to be+ out of normal computer units, but they do have lower/upper versions,+ so adding them seems the right thing.++## Version 0.2.0++*released Sun, 22 Nov 2015*+ * Incompatible API change to cleanup some initial design decisions: the two level `FormatOption`/`FormatMode` model is removed, the fixed unit of `FormatOption` is moved to a new constructor@@ -10,20 +34,26 @@ disables scaling; it should have the same effect without introducing an artificial unit. -Version 0.1.0.2+## Version 0.1.0.2 +*released Sun, 23 Nov 2014*+ * Trivial release for compatibility with QuickCheck 2.7 and older HUnit packages as found in Wheezy. * The release switches the test suite to use Cabal macros, which might create issues in some cases. * Fixed issue #2 (Wrong formatting for small numbers in SI mode). -Version 0.1.0.1+## Version 0.1.0.1 +*released Mon, 19 May 2014*+ * Trivial release updating upper package bounds (for testing), updating homepage/related settings as part of move to github, and fixing a few documentation issues. -Version 0.1.0+## Version 0.1.0++*released Thu, 03 May 2012* * Initial release.
Data/Prefix/Units.hs view
@@ -131,7 +131,9 @@ default () -- | The unit type.-data Unit = Yocto+data Unit = Quecto+ | Ronto+ | Yocto | Zepto | Atto | Femto@@ -157,13 +159,38 @@ | Exbi | Zetta | Yotta+ | Ronna+ | Quetta deriving (Show, Eq, Enum, Bounded, Ord) -- | List of all SI units. siUnits :: [Unit] siUnits- = [Yocto, Zepto, Atto, Femto, Pico, Nano, Micro, Milli, Centi,- Deci, Deka, Hecto, Kilo, Mega, Giga, Tera, Peta, Exa, Zetta, Yotta]+ = [ Quecto+ , Ronto+ , Yocto+ , Zepto+ , Atto+ , Femto+ , Pico+ , Nano+ , Micro+ , Milli+ , Centi+ , Deci+ , Deka+ , Hecto+ , Kilo+ , Mega+ , Giga+ , Tera+ , Peta+ , Exa+ , Zetta+ , Yotta+ , Ronna+ , Quetta+ ] -- | List of binary units. binaryUnits :: [Unit]@@ -194,90 +221,102 @@ -- >>> unitMultiplier Mebi -- 1048576 % 1 unitMultiplier :: Unit -> Rational-unitMultiplier Yocto = siBase ^^ (-24 :: Int)-unitMultiplier Zepto = siBase ^^ (-21 :: Int)-unitMultiplier Atto = siBase ^^ (-18 :: Int)-unitMultiplier Femto = siBase ^^ (-15 :: Int)-unitMultiplier Pico = siBase ^^ (-12 :: Int)-unitMultiplier Nano = siBase ^^ ( -9 :: Int)-unitMultiplier Micro = siBase ^^ ( -6 :: Int)-unitMultiplier Milli = siBase ^^ ( -3 :: Int)-unitMultiplier Centi = siBase ^^ ( -2 :: Int)-unitMultiplier Deci = siBase ^^ ( -1 :: Int)-unitMultiplier Deka = siBase ^^ ( 1 :: Int)-unitMultiplier Hecto = siBase ^^ ( 2 :: Int)-unitMultiplier Kilo = siBase ^^ ( 3 :: Int)-unitMultiplier Kibi = binaryBase ^^ ( 10 :: Int)-unitMultiplier Mega = siBase ^^ ( 6 :: Int)-unitMultiplier Mebi = binaryBase ^^ ( 20 :: Int)-unitMultiplier Giga = siBase ^^ ( 9 :: Int)-unitMultiplier Gibi = binaryBase ^^ ( 30 :: Int)-unitMultiplier Tera = siBase ^^ ( 12 :: Int)-unitMultiplier Tebi = binaryBase ^^ ( 40 :: Int)-unitMultiplier Peta = siBase ^^ ( 15 :: Int)-unitMultiplier Pebi = binaryBase ^^ ( 50 :: Int)-unitMultiplier Exa = siBase ^^ ( 18 :: Int)-unitMultiplier Exbi = binaryBase ^^ ( 60 :: Int)-unitMultiplier Zetta = siBase ^^ ( 21 :: Int)-unitMultiplier Yotta = siBase ^^ ( 24 :: Int)+unitMultiplier Quecto = siBase ^^ (-30 :: Int)+unitMultiplier Ronto = siBase ^^ (-27 :: Int)+unitMultiplier Yocto = siBase ^^ (-24 :: Int)+unitMultiplier Zepto = siBase ^^ (-21 :: Int)+unitMultiplier Atto = siBase ^^ (-18 :: Int)+unitMultiplier Femto = siBase ^^ (-15 :: Int)+unitMultiplier Pico = siBase ^^ (-12 :: Int)+unitMultiplier Nano = siBase ^^ ( -9 :: Int)+unitMultiplier Micro = siBase ^^ ( -6 :: Int)+unitMultiplier Milli = siBase ^^ ( -3 :: Int)+unitMultiplier Centi = siBase ^^ ( -2 :: Int)+unitMultiplier Deci = siBase ^^ ( -1 :: Int)+unitMultiplier Deka = siBase ^^ ( 1 :: Int)+unitMultiplier Hecto = siBase ^^ ( 2 :: Int)+unitMultiplier Kilo = siBase ^^ ( 3 :: Int)+unitMultiplier Kibi = binaryBase ^^ ( 10 :: Int)+unitMultiplier Mega = siBase ^^ ( 6 :: Int)+unitMultiplier Mebi = binaryBase ^^ ( 20 :: Int)+unitMultiplier Giga = siBase ^^ ( 9 :: Int)+unitMultiplier Gibi = binaryBase ^^ ( 30 :: Int)+unitMultiplier Tera = siBase ^^ ( 12 :: Int)+unitMultiplier Tebi = binaryBase ^^ ( 40 :: Int)+unitMultiplier Peta = siBase ^^ ( 15 :: Int)+unitMultiplier Pebi = binaryBase ^^ ( 50 :: Int)+unitMultiplier Exa = siBase ^^ ( 18 :: Int)+unitMultiplier Exbi = binaryBase ^^ ( 60 :: Int)+unitMultiplier Zetta = siBase ^^ ( 21 :: Int)+unitMultiplier Yotta = siBase ^^ ( 24 :: Int)+unitMultiplier Ronna = siBase ^^ ( 27 :: Int)+unitMultiplier Quetta = siBase ^^ ( 30 :: Int) -- | Returns the unit full name. unitName :: Unit -> String-unitName Yocto = "yocto"-unitName Zepto = "zepto"-unitName Atto = "atto"-unitName Femto = "femto"-unitName Pico = "pico"-unitName Nano = "nano"-unitName Micro = "micro"-unitName Milli = "milli"-unitName Centi = "centi"-unitName Deci = "deci"-unitName Deka = "deka"-unitName Hecto = "hecto"-unitName Kilo = "kilo"-unitName Kibi = "kibi"-unitName Mega = "mega"-unitName Mebi = "mebi"-unitName Giga = "giga"-unitName Gibi = "gibi"-unitName Tera = "tera"-unitName Tebi = "tebi"-unitName Peta = "peta"-unitName Pebi = "pebi"-unitName Exa = "exa"-unitName Exbi = "exbi"-unitName Zetta = "zetta"-unitName Yotta = "yotta"+unitName Quecto = "quecto"+unitName Ronto = "ronto"+unitName Yocto = "yocto"+unitName Zepto = "zepto"+unitName Atto = "atto"+unitName Femto = "femto"+unitName Pico = "pico"+unitName Nano = "nano"+unitName Micro = "micro"+unitName Milli = "milli"+unitName Centi = "centi"+unitName Deci = "deci"+unitName Deka = "deka"+unitName Hecto = "hecto"+unitName Kilo = "kilo"+unitName Kibi = "kibi"+unitName Mega = "mega"+unitName Mebi = "mebi"+unitName Giga = "giga"+unitName Gibi = "gibi"+unitName Tera = "tera"+unitName Tebi = "tebi"+unitName Peta = "peta"+unitName Pebi = "pebi"+unitName Exa = "exa"+unitName Exbi = "exbi"+unitName Zetta = "zetta"+unitName Yotta = "yotta"+unitName Ronna = "ronna"+unitName Quetta = "quetta" -- | Returns the unit ASCII symbol. unitSymbol :: Unit -> String-unitSymbol Yocto = "y"-unitSymbol Zepto = "z"-unitSymbol Atto = "a"-unitSymbol Femto = "f"-unitSymbol Pico = "p"-unitSymbol Nano = "n"-unitSymbol Micro = "u"-unitSymbol Milli = "m"-unitSymbol Centi = "c"-unitSymbol Deci = "d"-unitSymbol Deka = "da"-unitSymbol Hecto = "h"-unitSymbol Kilo = "k"-unitSymbol Kibi = "Ki"-unitSymbol Mega = "M"-unitSymbol Mebi = "Mi"-unitSymbol Giga = "G"-unitSymbol Gibi = "Gi"-unitSymbol Tera = "T"-unitSymbol Tebi = "Ti"-unitSymbol Peta = "P"-unitSymbol Pebi = "Pi"-unitSymbol Exa = "E"-unitSymbol Exbi = "Ei"-unitSymbol Zetta = "Z"-unitSymbol Yotta = "Y"+unitSymbol Quecto = "q"+unitSymbol Ronto = "r"+unitSymbol Yocto = "y"+unitSymbol Zepto = "z"+unitSymbol Atto = "a"+unitSymbol Femto = "f"+unitSymbol Pico = "p"+unitSymbol Nano = "n"+unitSymbol Micro = "u"+unitSymbol Milli = "m"+unitSymbol Centi = "c"+unitSymbol Deci = "d"+unitSymbol Deka = "da"+unitSymbol Hecto = "h"+unitSymbol Kilo = "k"+unitSymbol Kibi = "Ki"+unitSymbol Mega = "M"+unitSymbol Mebi = "Mi"+unitSymbol Giga = "G"+unitSymbol Gibi = "Gi"+unitSymbol Tera = "T"+unitSymbol Tebi = "Ti"+unitSymbol Peta = "P"+unitSymbol Pebi = "Pi"+unitSymbol Exa = "E"+unitSymbol Exbi = "Ei"+unitSymbol Zetta = "Z"+unitSymbol Yotta = "Y"+unitSymbol Ronna = "R"+unitSymbol Quetta = "Q" -- | Returns the unit symbol, which for the 'Micro' unit is not ASCII. fancySymbol :: Unit -> String@@ -410,6 +449,8 @@ -- | Parses a symbol in the exact mode. See 'ParseExact' for details. parseExactSymbol :: String -> Either String Unit+parseExactSymbol "q" = Right Quecto+parseExactSymbol "r" = Right Ronto parseExactSymbol "y" = Right Yocto parseExactSymbol "z" = Right Zepto parseExactSymbol "a" = Right Atto@@ -436,6 +477,8 @@ parseExactSymbol "Ei" = Right Exbi parseExactSymbol "Z" = Right Zetta parseExactSymbol "Y" = Right Yotta+parseExactSymbol "R" = Right Ronna+parseExactSymbol "Q" = Right Quetta parseExactSymbol unit = unknownUnit unit -- | Helper for 'parseBinarySymbol' which only deals with upper-case@@ -476,6 +519,8 @@ helperParseKMGT "EI" = Right Exbi helperParseKMGT "Z" = Right Zetta helperParseKMGT "Y" = Right Yotta+helperParseKMGT "R" = Right Ronna+helperParseKMGT "Q" = Right Quetta -- FIXME: error message will contain upper-case version of the symbol helperParseKMGT symbol = unknownUnit symbol
README.md view
@@ -25,6 +25,9 @@ the use of some hand-coded conversions instead of using TemplateHaskell to generate them automatically. +[](https://github.com/iustin/prefix-units/actions/workflows/ci.yml)+[](https://codecov.io/gh/iustin/prefix-units)+ TODO ---- @@ -32,7 +35,7 @@ composable. I'm still looking for a nicer way to expose the parsing functionality. -Currently, the binary and SI units are mixed in the same+Currently, the IEC (binary) and SI units are mixed in the same data-type. This works, but at some level I think two separate types would be more "correct", at the expense of a more complex API.
prefix-units.cabal view
@@ -1,86 +1,97 @@+cabal-version: 1.18 -- prefix-units.cabal auto-generated by cabal init. For additional -- options, see -- http://www.haskell.org/cabal/release/cabal-latest/doc/users-guide/authors.html#pkg-descr. -- The name of the package.-Name: prefix-units+name: prefix-units -- The package version. See the Haskell package versioning policy -- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for -- standards guiding when and how versions should be incremented.-Version: 0.2.0+version: 0.3.0.1 -- A short (one-line) description of the package.-Synopsis: A basic library for SI/binary prefix units+synopsis: A basic library for SI/IEC prefix units -- A longer description of the package.-Description:+description: This library deals with parsing values containing \"prefix units\"- (both binary and SI). For example, it can parse 10M and 1G, and it- can also format values for displaying with the \"optimal\" unit.+ (both IEC\/binary and SI). For example, it can parse 10M and 1G,+ and it can also format values for displaying with the \"optimal\"+ unit. For more details, see the man page units(7), <http://physics.nist.gov/cuu/Units/prefixes.html> and <http://physics.nist.gov/cuu/Units/binary.html>. -- URL for the project homepage or repository.-Homepage: https://github.com/iustin/prefix-units+homepage: https://github.com/iustin/prefix-units -- The license under which the package is released.-License: BSD3+license: BSD3 -- The file containing the license text.-License-file: LICENSE+license-file: LICENSE -- The package author(s).-Author: Iustin Pop <iustin@google.com>+author: Iustin Pop <iustin@google.com> -- An email address to which users can send suggestions, bug reports, -- and patches.-Maintainer: Iustin Pop <iustin@google.com>+maintainer: Iustin Pop <iustin@google.com> -- A copyright notice.-Copyright: (c) 2012, 2014, 2015 Google Inc.+copyright: (c) 2012, 2014, 2015 Google Inc. -Category: Data+category: Data -- Stability field.-Stability: alpha+stability: stable -Bug-reports: https://github.com/iustin/prefix-units/issues+bug-reports: https://github.com/iustin/prefix-units/issues -Build-type: Simple+build-type: Simple -- Extra files to be distributed with the package, such as examples or -- a README.-Extra-source-files: README.md CHANGES.md Makefile example.hs---- Constraint on the version of Cabal needed to build this package.-Cabal-version: >= 1.8.0.2+extra-source-files: README.md CHANGES.md Makefile example.hs -Tested-with: GHC==7.6.3, GHC==7.8.4, GHC==7.10.2+tested-with: GHC==8.0.2+ , GHC==8.2.2+ , GHC==8.4+ , GHC==8.6+ , GHC==8.8+ , GHC==8.10+ , GHC==9.0+ , GHC==9.2+ , GHC==9.4+ , GHC==9.6 -Source-repository head+source-repository head Type: git Location: https://github.com/iustin/prefix-units.git -Source-repository this+source-repository this Type: git Location: https://github.com/iustin/prefix-units.git Tag: prefix-units-v0.2.0 -Library+library -- Modules exported by the library.- Exposed-modules: Data.Prefix.Units+ exposed-modules: Data.Prefix.Units -- Packages needed in order to build this package.- Build-depends: base >= 3 && < 5+ build-depends: base >= 3 && < 5 -- Modules not exported by this package.- Other-modules: Data.Prefix.Units.Compat+ other-modules: Data.Prefix.Units.Compat - GHC-Options: -Wall+ ghc-options: -Wall - Extensions: Safe+ default-language: Haskell2010++ default-extensions:+ Safe TypeSynonymInstances FlexibleInstances @@ -98,7 +109,11 @@ , test-framework-hunit >= 0.2.7 , QuickCheck >= 2.4.2 , HUnit >= 1.2.4+ , deepseq >= 1.4.0.0 , prefix-units ghc-options: -Wall -fno-warn-orphans- Extensions: CPP+ default-extensions:+ CPP ScopedTypeVariables++ default-language: Haskell2010
tests/Properties.hs view
@@ -40,6 +40,7 @@ module Main (main) where import Control.Applicative (pure, (<$>))+import Control.DeepSeq (force) import Data.Char (toUpper) import Data.List import Data.Maybe (isNothing)@@ -125,6 +126,12 @@ instance Arbitrary ParseMode where arbitrary = elements [minBound..maxBound] +instance Arbitrary ParseOptions where+ arbitrary = oneof [ pure UnitRequired+ , UnitDefault <$> arbitrary+ , pure UnitOptional+ ]+ allUnits :: [Unit] allUnits = [minBound..maxBound] @@ -221,7 +228,7 @@ -- | Fail to parse invalid symbols in any mode. testSymbolParsingFail :: ParseMode -> Property testSymbolParsingFail mode =- expectParseFailure (("NO-SUCH" `isInfixOf`) . map toUpper) $+ expectParseFailure (("NO-SUCH" `isInfixOf`) . force . map toUpper) $ parseSymbol mode "no-such" -- | Parsed values should be correct.@@ -270,13 +277,13 @@ testFailParsing :: ParseMode -> Int -> Property testFailParsing pmode v =- expectParseFailure ("no-such" `isInfixOf`)+ expectParseFailure (("no-such" `isInfixOf`) . force) (parseValue pmode ("no-such" ++ show v)::Either String Int) -- | Test fail parse on required unit. testParsingRequired :: ParseMode -> Int -> Property testParsingRequired pmode v =- expectParseFailure ("is required" `isInfixOf`)+ expectParseFailure (("is required" `isInfixOf`) . force) (parseGeneric UnitRequired [] pmode (show v)::Either String Int) testParsingDefault :: Unit -> ParseMode -> Rational -> Property@@ -287,7 +294,7 @@ testParsingInvalidList :: Unit -> [Unit] -> Int -> Property testParsingInvalidList unit valid v = unit `notElem` valid && not (null valid) ==>- expectParseFailure ("not part of the accepted unit list" `isInfixOf`)+ expectParseFailure (("not part of the accepted unit list" `isInfixOf`) . force) (parseGeneric UnitOptional valid ParseExact (show v ++ unitSymbol unit)::Either String Int) @@ -410,6 +417,18 @@ "': " ++ err) Right val' -> val ==? val' +-- | Trivial assertion that the Show instance works+testFormatModeShow :: FormatMode -> Property+testFormatModeShow = total . show++-- | Trivial assertion that the Show instance works+testParseModeShow :: ParseMode -> Property+testParseModeShow = total . show++-- | Trivial assertion that the Show instance works+testParseOptionsShow :: ParseOptions -> Property+testParseOptionsShow = total . show+ -- * Test harness main :: IO ()@@ -462,5 +481,8 @@ ] , testGroup "round-trip" [ testProperty "rational round-trip" testRoundTripRational+ , testProperty "format mode show" testFormatModeShow+ , testProperty "parse mode show" testParseModeShow+ , testProperty "parse options show" testParseOptionsShow ] ]