Generically derived enumerations.
This package provides a way to generically obtain every possible value of a type, provided that the generic representation of the type is compatible.
generic-enumeration
This is a library that provides generics-based enumeration of all possible values for a type.
It differs from deriving Enum
in that:
- It supports non-nullary data constructors.
- It does not try for integer encoding/decoding. It works by providing a list containing every value, and also providing
succMay
andpredMay
analogs to Enum'ssucc
andpred
- It does not allow user-defined instances. Instances either work generically or they don't.
Because of this it is a little less powerful that Enum
in some cases, but it is also a lot more safe. There are no partial functions, and disallowing user-defined instances means that not even a human can mess it up.
Use case
I wrote this to solve a particular kind of problem I often have. When I have a type:
data A
= A1
| A2
| A3
deriving (Enum, Bounded)
And I want to produce a list of all the values:
allAs :: [A]
allAs = [minBound .. maxBound]
This `deriving (Enum, Bounded)` and `[minBound .. maxBound]` dance is a little awkward, and it is not always the case `Enum` or `Bounded` is meaningful for the type except as an implementation detail for getting the full list of values. Worse, this doesn't even work for types with non-nullary constructors. E.g. this won't compile:
data A
= A1 B
| A2 C
| A3
deriving (Enum, Bounded)
data B
= B1
| B2
deriving (Enum, Bounded)
data C
= C1
| C2
deriving (Enum, Bounded)
On the other hand, this will compile just fine:
data A
= A1 B
| A2 C
| A3
deriving (Generic)
data B
= B1
| B2
deriving (Generic)
data C
= C1
| C2
deriving (Generic)
allAs :: [A]
allAs = enumeration
-- where `enumeration` is a function from this package.
-- Has the value `[A1 B1, A1 B2, A2 C1, A2 C2, A3]`