QuickCheck 2.12.2 → 2.12.3
raw patch · 5 files changed
+61/−34 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Test.QuickCheck: shrinkDecimal :: RealFrac a => a -> [a]
+ Test.QuickCheck.Arbitrary: shrinkDecimal :: RealFrac a => a -> [a]
Files
- QuickCheck.cabal +2/−2
- Test/QuickCheck.hs +1/−0
- Test/QuickCheck/Arbitrary.hs +44/−26
- changelog +11/−3
- tests/Generators.hs +3/−3
QuickCheck.cabal view
@@ -1,5 +1,5 @@ Name: QuickCheck-Version: 2.12.2+Version: 2.12.3 Cabal-Version: >= 1.8 Build-type: Simple License: BSD3@@ -55,7 +55,7 @@ source-repository this type: git location: https://github.com/nick8325/quickcheck- tag: 2.12.2+ tag: 2.12.3 flag templateHaskell Description: Build Test.QuickCheck.All, which uses Template Haskell.
Test/QuickCheck.hs view
@@ -80,6 +80,7 @@ , shrinkMapBy , shrinkIntegral , shrinkRealFrac+ , shrinkDecimal -- ** Lifting of 'Arbitrary' to unary and binary type constructors , Arbitrary1(..)
Test/QuickCheck/Arbitrary.hs view
@@ -66,6 +66,7 @@ , shrinkMapBy -- :: (a -> b) -> (b -> a) -> (a -> [a]) -> b -> [b] , shrinkIntegral -- :: Integral a => a -> [a] , shrinkRealFrac -- :: RealFrac a => a -> [a]+ , shrinkDecimal -- :: RealFrac a => a -> [a] -- ** Helper functions for implementing coarbitrary , coarbitraryIntegral -- :: Integral a => a -> Gen b -> Gen b , coarbitraryReal -- :: Real a => a -> Gen b -> Gen b@@ -492,7 +493,7 @@ #ifndef NO_FIXED instance HasResolution a => Arbitrary (Fixed a) where arbitrary = arbitrarySizedFractional- shrink = shrinkRealFrac+ shrink = shrinkDecimal #endif instance Arbitrary2 (,) where@@ -676,11 +677,11 @@ instance Arbitrary Float where arbitrary = arbitrarySizedFractional- shrink = shrinkRealFrac+ shrink = shrinkDecimal instance Arbitrary Double where arbitrary = arbitrarySizedFractional- shrink = shrinkRealFrac+ shrink = shrinkDecimal instance Arbitrary CChar where arbitrary = arbitrarySizedBoundedIntegral@@ -782,11 +783,11 @@ instance Arbitrary CFloat where arbitrary = arbitrarySizedFractional- shrink = shrinkRealFrac+ shrink = shrinkDecimal instance Arbitrary CDouble where arbitrary = arbitrarySizedFractional- shrink = shrinkRealFrac+ shrink = shrinkDecimal -- Arbitrary instances for container types instance (Ord a, Arbitrary a) => Arbitrary (Set.Set a) where@@ -1096,29 +1097,46 @@ (True, False) -> a + b < 0 (False, True) -> a + b > 0 --- | Shrink a fraction, via continued-fraction approximations.+-- | Shrink a fraction, preferring numbers with smaller+-- numerators or denominators. See also 'shrinkDecimal'. shrinkRealFrac :: RealFrac a => a -> [a]-shrinkRealFrac a = shrinkRealFracToPrecision (abs a*1e-6) a+shrinkRealFrac x+ | not (x == x) = 0 : take 10 (iterate (*2) 0) -- NaN+ | not (2*x+1>x) = 0 : takeWhile (<x) (iterate (*2) 0) -- infinity+ | x < 0 = negate x:map negate (shrinkRealFrac (negate x))+ | otherwise =+ -- To ensure termination+ filter (\y -> abs y < abs x) $+ -- Try shrinking to an integer first+ map fromInteger (shrink (truncate x) ++ [truncate x]) +++ -- Shrink the numerator+ [fromRational (num' % denom) | num' <- shrink num] +++ -- Shrink the denominator, and keep the fraction as close+ -- to the original as possible, rounding towards zero+ [fromRational (truncate (num * denom' % denom) % denom')+ | denom' <- shrink denom, denom' /= 0 ]+ where+ num = numerator (toRational x)+ denom = denominator (toRational x) -shrinkRealFracToPrecision :: RealFrac a- => a -- ^ "Epsilon" – the minimum deviation we consider- -> a -- ^ Value to shrink- -> [a]-shrinkRealFracToPrecision eps x- | x < 0 = 0 : ([id, negate] <*> filter (>0) (shrinkRealFracToPrecision eps $ -x))- | x < eps = [0 | x /= 0]- | not (x==x) = []- | not (2*x>x) = 0 : takeWhile (<x) ((2^).(^2)<$>[0..])- | (x-intgPart>eps)- = filter (/= x) $- intgShrinks ++ [intgPart]- ++ map ((intgPart+) . recip)- (filter (>0)- . shrinkRealFracToPrecision (eps/(x-intgPart))- $ 1/(x-intgPart))- | otherwise = intgShrinks- where intgPart = fromInteger $ truncate x- intgShrinks = map fromInteger . shrinkIntegral $ truncate x+-- | Shrink a real number, preferring numbers with shorter+-- decimal representations. See also 'shrinkRealFrac'.+shrinkDecimal :: RealFrac a => a -> [a]+shrinkDecimal x+ | not (x == x) = 0 : take 10 (iterate (*2) 0) -- NaN+ | not (2*x+1>x) = 0 : takeWhile (<x) (iterate (*2) 0) -- infinity+ | otherwise =+ -- e.g. shrink pi =+ -- shrink 3 ++ map (/ 10) (shrink 31) +++ -- map (/ 100) (shrink 314) + ...,+ -- where the inner calls to shrink use integer shrinking.+ [ y+ | precision <- take 6 (iterate (*10) 1),+ let m = truncate (toRational x * precision),+ m `mod` 10 /= 0, -- don't allow shrinking to increase digits+ n <- m:shrink m,+ let y = fromRational (fromInteger n / precision),+ abs y < abs x ] -------------------------------------------------------------------------- -- ** CoArbitrary
changelog view
@@ -1,4 +1,12 @@-QuickCheck 2.12.2 (released 2018-09-06)+QuickCheck 2.12.3 (released 2018-09-12)+ * Shrinking for Float and Decimal now works by reducing the number+ of digits in the number. The new function shrinkDecimal+ implements this shrinking behaviour.+ * Shrinking for Rational now tries to make the numerator and+ denominator of the number smaller. Previously it tried to reduce+ the magnitude of the number.++QuickCheck 2.12.2 (released 2018-09-10) * Fix infinite shrinking loop for fractional types. * Add SortedList modifier. @@ -22,7 +30,7 @@ case distribution more flexibly than label. - When label is called multiple times in a property, each call produces a separate table of frequencies.- + * New functions: - (=/=): like (/=), but prints a counterexample (thanks to tom-bop)@@ -50,7 +58,7 @@ argument is not evaluated and the whole disjunction is considered to have a false precondition - Bug fix: suchThatMaybe always increased size to at least 1- + * Miscellaneous API changes: - Result type has changed a bit: - InsufficientCovered constructor is gone
tests/Generators.hs view
@@ -14,14 +14,14 @@ instance Arbitrary a => Arbitrary (Path a) where arbitrary = do x <- arbitrary- fmap Path (pathFrom x)+ fmap Path (pathFrom 100 x) where- pathFrom x = sized $ \n ->+ pathFrom n x = fmap (x:) $ case shrink x of [] -> return [] _ | n == 0 -> return []- ys -> oneof [resize (n-1) (pathFrom y) | y <- ys]+ ys -> oneof [pathFrom (n-1) y | y <- ys] shrink (Path xs) = map Path [ ys | ys <- inits xs, length ys > 0 && length ys < length xs ]