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 shrinkBoundedEnum function. #350

Merged

Conversation

jonathanknowles
Copy link
Contributor

@jonathanknowles jonathanknowles commented Jan 17, 2023

This PR adds a new function shrinkBoundedEnum, which should resolve issue #343.

The shrinkBoundedEnum function provides a counterpart to the pre-existing arbitraryBoundedEnum function. Together, they can be used to define a complete Arbitrary instance for a bounded enumeration data type.

For example, let's say we have the following (admittedly contrived) type:

data MyEnum
   = E00 | E01 | E02 | E03 | E04 | E05 | E06 | E07 | E08 | E09
   | E10 | E11 | E12 | E13 | E14 | E15 | E16 | E17 | E18 | E19
   | E20 | E21 | E22 | E23 | E24 | E25 | E26 | E27 | E28 | E29
   | E30 | E31 | E32 | E33 | E34 | E35 | E36 | E37 | E38 | E39
   | E40 | E41 | E42 | E43 | E44 | E45 | E46 | E47 | E48 | E49
   | E50 | E51 | E52 | E53 | E54 | E55 | E56 | E57 | E58 | E59
   | E60 | E61 | E62 | E63 | E64 | E65 | E66 | E67 | E68 | E69
   | E70 | E71 | E72 | E73 | E74 | E75 | E76 | E77 | E78 | E79
   | E80 | E81 | E82 | E83 | E84 | E85 | E86 | E87 | E88 | E89
   | E90 | E91 | E92 | E93 | E94 | E95 | E96 | E97 | E98 | E99
   deriving (Bounded, Enum, Eq, Ord, Show)

We can then define the following Arbitrary instance:

instance Arbitrary MyEnum where
    arbitrary = arbitraryBoundedEnum
    shrink = shrinkBoundedEnum

Since shrinkBoundedEnum reuses shrinkIntegral internally, we get similar shrinking behaviour: values earlier in the shrink list are shrunk more aggressively, followed by the usual exponential back-off:

>>> shrinkBoundedEnum E99
[E00,E50,E75,E87,E93,E96,E98]
>>> shrinkBoundedEnum E49
[E00,E25,E37,E43,E46,E48]
>>> shrinkBoundedEnum E00
[]

The `shrinkBoundedEnum` function provides a counterpart to the
pre-existing `arbitraryBoundedEnum` function.

Together, they can be used to define a complete `Arbitrary` instance for
a bounded enumeration data type.

For example, let's say we have the following type:

```hs
data MyEnum
    = E00 | E01 | E02 | E03 | E04 | E05 | E06 | E07 | E08 | E09
    | E10 | E11 | E12 | E13 | E14 | E15 | E16 | E17 | E18 | E19
    | E20 | E21 | E22 | E23 | E24 | E25 | E26 | E27 | E28 | E29
    | E30 | E31 | E32 | E33 | E34 | E35 | E36 | E37 | E38 | E39
    | E40 | E41 | E42 | E43 | E44 | E45 | E46 | E47 | E48 | E49
    | E50 | E51 | E52 | E53 | E54 | E55 | E56 | E57 | E58 | E59
    | E60 | E61 | E62 | E63 | E64 | E65 | E66 | E67 | E68 | E69
    | E70 | E71 | E72 | E73 | E74 | E75 | E76 | E77 | E78 | E79
    | E80 | E81 | E82 | E83 | E84 | E85 | E86 | E87 | E88 | E89
    | E90 | E91 | E92 | E93 | E94 | E95 | E96 | E97 | E98 | E99
  deriving (Bounded, Enum, Eq, Ord, Show)
```

We can then define the following arbitrary instance:
```
instance Arbitrary MyEnum where
  arbitrary = arbitraryBoundedEnum
  shrink = shrinkBoundedEnum
```

Since `shrinkBoundedEnum` reuses `shrinkIntegral` internally, we get similar
shrinking behaviour.

Values earlier in the shrink list are shrunk more aggressively, followed
by exponential back-off:

```hs
>>> shrinkBoundedEnum E99
[E00,E50,E75,E87,E93,E96,E98]
```

```hs
>>> shrinkBoundedEnum E49
[E00,E25,E37,E43,E46,E48]
```

```hs
>>> shrinkBoundedEnum E01
[E00]
```

```hs
>>> shrinkBoundedEnum E00
[]
```
@jonathanknowles
Copy link
Contributor Author

Hi @nick8325

Just wondering if you think this function would be useful? If you like the idea, but you'd like me to make revisions to it -- let me know, would be happy to do so.

All the best!
Jonathan

@nick8325
Copy link
Owner

It looks good! Thanks for the patch!

@nick8325 nick8325 merged commit 272ce3c into nick8325:master Mar 12, 2023
@jonathanknowles jonathanknowles deleted the jonathanknowles/shrinkBoundedEnum branch March 12, 2023 11:49
@jonathanknowles
Copy link
Contributor Author

It looks good! Thanks for the patch!

You're welcome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants