packages feed

unwitch 2.0.1 → 2.0.2

raw patch · 28 files changed

+137/−3 lines, 28 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

Changelog.md view
@@ -1,5 +1,13 @@ # Change log for unwitch project +## Version 2.0.2++ Wire up 9 missing test specs that existed but were not included in the test runner++ Add module-level haddock to all Convert modules, Errors, and Constant++ Add haddock to Overflows type and constructors++ Expand property tests with 20+ new properties covering Int/Word+  same-width conversions, Float/Double range checks, cross-sign+  narrowing, Ratio round-trips, and Fixed round-trips+ ## Version 2.0.1 + Add haddock section headers separating boxed and unboxed conversions + Each module with unboxed functions now has "Conversions" and
src/Unwitch/Constant.hs view
@@ -1,3 +1,4 @@+-- | Constants used for range-checking floating-point conversions. module Unwitch.Constant   ( maxIntegralRepDouble   , maxIntegralRepFloat
src/Unwitch/Convert/ByteString.hs view
@@ -1,3 +1,4 @@+-- | Conversions from 'Data.ByteString.ByteString'. module Unwitch.Convert.ByteString   ( toLazyByteString   , toShortByteString
src/Unwitch/Convert/Char.hs view
@@ -1,3 +1,4 @@+-- | Conversions from 'Char'. module Unwitch.Convert.Char   ( -- * Conversions     toInt
src/Unwitch/Convert/Double.hs view
@@ -1,3 +1,4 @@+-- | Conversions from 'Double'. module Unwitch.Convert.Double   ( toFloat   , toFixed
src/Unwitch/Convert/Fixed.hs view
@@ -1,3 +1,4 @@+-- | Conversions from 'Data.Fixed.Fixed'. module Unwitch.Convert.Fixed   ( fromInteger   , toInteger
src/Unwitch/Convert/Float.hs view
@@ -1,3 +1,4 @@+-- | Conversions from 'Float'. module Unwitch.Convert.Float   ( toDouble   , toRational
src/Unwitch/Convert/Int.hs view
@@ -1,3 +1,4 @@+-- | Conversions from 'Int'. module Unwitch.Convert.Int   ( -- * Conversions     toInt8
src/Unwitch/Convert/Int16.hs view
@@ -1,3 +1,4 @@+-- | Conversions from 'Int16'. module Unwitch.Convert.Int16   ( -- * Conversions     toInt8
src/Unwitch/Convert/Int32.hs view
@@ -1,3 +1,4 @@+-- | Conversions from 'Int32'. module Unwitch.Convert.Int32   ( -- * Conversions     toInt8
src/Unwitch/Convert/Int64.hs view
@@ -1,3 +1,4 @@+-- | Conversions from 'Int64'. module Unwitch.Convert.Int64   ( -- * Conversions     toInt8
src/Unwitch/Convert/Int8.hs view
@@ -1,3 +1,4 @@+-- | Conversions from 'Int8'. module Unwitch.Convert.Int8   ( -- * Conversions     toInt16
src/Unwitch/Convert/Integer.hs view
@@ -1,3 +1,4 @@+-- | Conversions from 'Integer'. module Unwitch.Convert.Integer   ( -- * Conversions     toDouble
src/Unwitch/Convert/LazyByteString.hs view
@@ -1,3 +1,4 @@+-- | Conversions from lazy 'Data.ByteString.Lazy.ByteString'. module Unwitch.Convert.LazyByteString   ( toByteString   , toWord8s
src/Unwitch/Convert/LazyText.hs view
@@ -1,3 +1,4 @@+-- | Conversions from lazy 'Data.Text.Lazy.Text'. module Unwitch.Convert.LazyText   ( toText   , toString
src/Unwitch/Convert/Natural.hs view
@@ -1,3 +1,4 @@+-- | Conversions from 'Natural'. module Unwitch.Convert.Natural   ( -- * Conversions     toWord8
src/Unwitch/Convert/Ratio.hs view
@@ -1,3 +1,4 @@+-- | Conversions from 'Data.Ratio.Ratio'. module Unwitch.Convert.Ratio   ( unwrapIfDenominatorOne   , fromIntegralToRatio
src/Unwitch/Convert/ShortByteString.hs view
@@ -1,3 +1,4 @@+-- | Conversions from 'Data.ByteString.Short.ShortByteString'. module Unwitch.Convert.ShortByteString   ( toByteString   , toWord8s
src/Unwitch/Convert/Text.hs view
@@ -1,3 +1,4 @@+-- | Conversions from 'Data.Text.Text'. module Unwitch.Convert.Text   ( toLazyText   , toString
src/Unwitch/Convert/Word.hs view
@@ -1,3 +1,4 @@+-- | Conversions from 'Word'. module Unwitch.Convert.Word   ( -- * Conversions     toWord8
src/Unwitch/Convert/Word16.hs view
@@ -1,3 +1,4 @@+-- | Conversions from 'Word16'. module Unwitch.Convert.Word16   ( -- * Conversions     toWord8
src/Unwitch/Convert/Word32.hs view
@@ -1,3 +1,4 @@+-- | Conversions from 'Word32'. module Unwitch.Convert.Word32   ( -- * Conversions     toWord8
src/Unwitch/Convert/Word64.hs view
@@ -1,3 +1,4 @@+-- | Conversions from 'Word64'. module Unwitch.Convert.Word64   ( -- * Conversions     toWord8
src/Unwitch/Convert/Word8.hs view
@@ -1,3 +1,4 @@+-- | Conversions from 'Word8'. module Unwitch.Convert.Word8   ( -- * Conversions     toWord16
src/Unwitch/Errors.hs view
@@ -1,8 +1,12 @@+-- | Error types for fallible numeric conversions. module Unwitch.Errors   ( Overflows(..)   ) where -data Overflows = Overflow-               | Underflow+-- | Indicates that a numeric conversion failed because the source+-- value is outside the representable range of the target type.+data Overflows+  = Overflow   -- ^ The source value is above the target's upper bound.+  | Underflow  -- ^ The source value is below the target's lower bound.   deriving (Show, Eq)
test/Spec.hs view
@@ -16,6 +16,15 @@ import qualified Test.Convert.FloatSpec import qualified Test.Convert.DoubleSpec import qualified Test.Convert.PropertySpec+import qualified Test.Convert.CharSpec+import qualified Test.Convert.FixedSpec+import qualified Test.Convert.RatioSpec+import qualified Test.Convert.TextSpec+import qualified Test.Convert.LazyTextSpec+import qualified Test.Convert.ByteStringSpec+import qualified Test.Convert.LazyByteStringSpec+import qualified Test.Convert.ShortByteStringSpec+import qualified Test.Convert.UnboxedSpec  main :: IO () main = hspec $ do@@ -33,4 +42,13 @@   Test.Convert.IntegerSpec.spec   Test.Convert.FloatSpec.spec   Test.Convert.DoubleSpec.spec+  Test.Convert.CharSpec.spec+  Test.Convert.FixedSpec.spec+  Test.Convert.RatioSpec.spec+  Test.Convert.TextSpec.spec+  Test.Convert.LazyTextSpec.spec+  Test.Convert.ByteStringSpec.spec+  Test.Convert.LazyByteStringSpec.spec+  Test.Convert.ShortByteStringSpec.spec+  Test.Convert.UnboxedSpec.spec   Test.Convert.PropertySpec.spec
test/Test/Convert/PropertySpec.hs view
@@ -5,6 +5,8 @@ import Test.Hspec.QuickCheck (prop) import Data.Int import Data.Word+import Data.Fixed (Fixed, E6)+import Data.Ratio (Ratio) import qualified Unwitch.Convert.Int8 as Int8 import qualified Unwitch.Convert.Int16 as Int16 import qualified Unwitch.Convert.Int32 as Int32@@ -20,6 +22,8 @@ import qualified Unwitch.Convert.Char as Char import qualified Unwitch.Convert.Float as Float import qualified Unwitch.Convert.Double as Double+import qualified Unwitch.Convert.Ratio as Ratio+import qualified Unwitch.Convert.Fixed as Fixed import Numeric.Natural (Natural)  spec :: Spec@@ -398,6 +402,25 @@     prop "Int64 -> Word64: Nothing iff x < 0" $ \(x :: Int64) ->       (Int64.toWord64 x == Nothing) `shouldBe` (x < 0) +    prop "Int -> Word: Nothing iff x < 0" $ \(x :: Int) ->+      (Int.toWord x == Nothing) `shouldBe` (x < 0)++  describe "Unsigned-to-signed same-width: exact failure condition" $ do+    prop "Word8 -> Int8: Nothing iff x > 127" $ \(x :: Word8) ->+      (Word8.toInt8 x == Nothing) `shouldBe` (x > 127)++    prop "Word16 -> Int16: Nothing iff x > 32767" $ \(x :: Word16) ->+      (Word16.toInt16 x == Nothing) `shouldBe` (x > 32767)++    prop "Word32 -> Int32: Nothing iff x > 2147483647" $ \(x :: Word32) ->+      (Word32.toInt32 x == Nothing) `shouldBe` (x > 2147483647)++    prop "Word64 -> Int64: Nothing iff x > fromIntegral (maxBound :: Int64)" $ \(x :: Word64) ->+      (Word64.toInt64 x == Nothing) `shouldBe` (x > fromIntegral (maxBound :: Int64))++    prop "Word -> Int: Nothing iff x > fromIntegral (maxBound :: Int)" $ \(x :: Word) ->+      (Word.toInt x == Nothing) `shouldBe` (x > fromIntegral (maxBound :: Int))+   describe "Cross-sign narrowing: exact failure condition" $ do     prop "Int16 -> Word8: Nothing iff x < 0 || x > 255" $ \(x :: Int16) ->       (Int16.toWord8 x == Nothing) `shouldBe` (x < 0 || x > 255)@@ -417,6 +440,54 @@     prop "Word64 -> Int32: Nothing iff x > 2147483647" $ \(x :: Word64) ->       (Word64.toInt32 x == Nothing) `shouldBe` (x > 2147483647) +    prop "Int -> Word8: Nothing iff x < 0 || x > 255" $ \(x :: Int) ->+      (Int.toWord8 x == Nothing) `shouldBe` (x < 0 || x > 255)++    prop "Int -> Word16: Nothing iff x < 0 || x > 65535" $ \(x :: Int) ->+      (Int.toWord16 x == Nothing) `shouldBe` (x < 0 || x > 65535)++    prop "Int -> Word32: Nothing iff x < 0 || x > 4294967295" $ \(x :: Int) ->+      (Int.toWord32 x == Nothing) `shouldBe` (x < 0 || x > 4294967295)++    prop "Word -> Int8: Nothing iff x > 127" $ \(x :: Word) ->+      (Word.toInt8 x == Nothing) `shouldBe` (x > 127)++    prop "Word -> Int16: Nothing iff x > 32767" $ \(x :: Word) ->+      (Word.toInt16 x == Nothing) `shouldBe` (x > 32767)++    prop "Word -> Int32: Nothing iff x > 2147483647" $ \(x :: Word) ->+      (Word.toInt32 x == Nothing) `shouldBe` (x > 2147483647)++  describe "Int/Word/Natural Float range check" $ do+    prop "Int -> Float: succeeds iff abs value <= maxRepFloat" $ \(x :: Int) ->+      let xi = fromIntegral x :: Integer+      in isRight (Int.toFloat x) `shouldBe`+           (xi >= -maxRepFloat && xi <= maxRepFloat)++    prop "Word -> Float: succeeds iff value <= maxRepFloat" $ \(x :: Word) ->+      isRight (Word.toFloat x) `shouldBe`+        (fromIntegral x <= (maxRepFloat :: Integer))++    prop "Natural -> Float: succeeds iff value <= maxRepFloat" $ \(w :: Word64) ->+      let x = fromIntegral w :: Natural+      in isRight (Natural.toFloat x) `shouldBe`+           (fromIntegral w <= (maxRepFloat :: Integer))++  describe "Int/Word/Natural Double range check" $ do+    prop "Int -> Double: succeeds iff abs value <= maxRepDouble" $ \(x :: Int) ->+      let xi = fromIntegral x :: Integer+      in isRight (Int.toDouble x) `shouldBe`+           (xi >= -maxRepDouble && xi <= maxRepDouble)++    prop "Word -> Double: succeeds iff value <= maxRepDouble" $ \(x :: Word) ->+      isRight (Word.toDouble x) `shouldBe`+        (fromIntegral x <= (maxRepDouble :: Integer))++    prop "Natural -> Double: succeeds iff value <= maxRepDouble" $ \(w :: Word64) ->+      let x = fromIntegral w :: Natural+      in isRight (Natural.toDouble x) `shouldBe`+           (fromIntegral w <= (maxRepDouble :: Integer))+   describe "Float/Double to integer: exact success condition" $ do     prop "Float -> Integer: succeeds iff finite and whole" $ \(x :: Float) ->       isRight (Float.toInteger x) `shouldBe` isWholeFloat x@@ -471,6 +542,16 @@       in if isNaN x          then y `shouldSatisfy` isNaN          else y `shouldBe` x++  describe "Ratio round-trip" $ do+    prop "Int8 -> Ratio Int8 -> Int8" $ \(x :: Int8) ->+      let r = Ratio.fromIntegralToRatio x :: Ratio Int8+      in Ratio.unwrapIfDenominatorOne r `shouldBe` Just x++  describe "Fixed round-trip" $ do+    prop "Integer -> Fixed E6 -> Integer for whole numbers" $ \(x :: Integer) ->+      let f = Fixed.fromInteger x :: Fixed E6+      in Fixed.toInteger f `shouldBe` Just x  maxRepFloat :: Num a => a maxRepFloat = 16777215
unwitch.cabal view
@@ -1,7 +1,7 @@ cabal-version:      3.0  name:           unwitch-version:        2.0.1+version:        2.0.2 homepage:       https://github.com/jappeace/unwitch#readme synopsis:  converts between primitives description: