Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add generating monotonic functions #348

Open
brandon-leapyear opened this issue Dec 7, 2022 · 0 comments
Open

Add generating monotonic functions #348

brandon-leapyear opened this issue Dec 7, 2022 · 0 comments

Comments

@brandon-leapyear
Copy link

brandon-leapyear commented Dec 7, 2022

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:

  1. Shrinking, the same way Fun does
  2. Make a new type class to support outputs that are integral or non-numerical
    • e.g. for Double -> Int, interpolate between the two ints, then round or truncate
  3. 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)
  4. More arbitrary interpolation
    • In this snippet, fractional indices do a linear interpolation between the two arguments, which is sufficient for my (most?) purposes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants