quickcheck
quickcheck copied to clipboard
Add generating monotonic functions
I was able to implement an arbitrary monotonic function like this:
-- | A modifier to generate monotonic functions
newtype Monotonic a b = Monotonic (a -> b)
instance Show (Monotonic a b) where
show _ = "<monotonic fun>"
instance (Show b, Real a, Arbitrary b, Fractional b, Real b, Ord b) => Arbitrary (Monotonic a b) where
arbitrary = do
x <- arbitrary
ups <- infiniteListMonotonic
downs <- infiniteListMonotonic
pure $ Monotonic $ \a ->
let (n, frac) = properFraction $ toRational a
(getIndex, index) =
if n >= 0
then (\i -> x + (ups !! i), n)
else (\i -> x - (downs !! i), (-n))
lo = getIndex index
hi = getIndex (index + 1)
in lo + fromRational frac * (hi - lo)
where
infiniteListMonotonic = scanl1 (+) . map getNonNegative <$> infiniteList
It would be great if this could be included in the base library, potentially with extra features like:
- Shrinking, the same way
Fundoes - Make a new type class to support outputs that are integral or non-numerical
- e.g. for
Double -> Int, interpolate between the two ints, thenroundortruncate
- e.g. for
- Make a new type class to support inputs that are still orderable, but non-numerical
- e.g.
data Octal = O0 | O1 | O2 | O3 | O4 | O5 | O6 | O7 arbitrary :: Gen (Octal -> Int) - More arbitrary interpolation
- In this snippet, fractional indices do a linear interpolation between the two arguments, which is sufficient for my (most?) purposes