Reputation: 3260
I have a snippet of code that looks something like this:
data SomeData = A | B | C | D | E deriving (Show, Enum)
and I want to be able to map certain values to these types easily. Say I wanted to have char
s mapped to a SomeData
type, I might do it like so:
mappings = zip "abcde" [A, B, C, D, E]
This would produce [('a',A),('b',B)...]
and so on. I was hoping that the Enum
type class might allow me to be able to do this easily by converting the data type into the list I described above ([A, B, C, D, E]
) by use of some convenience function.
Is there such a function in the standard library? Or would I need to define it myself if I wanted to use something like this?
Upvotes: 3
Views: 394
Reputation: 32455
Generally, I'd do
mappings = zip "abcde" [A..]
but I'd be very tempted to go with
mappings = zip ['a' ..] [A ..]
so that if I added other letters later, the code would update.
Going with maximally future-proof work I'd define
import Data.Char
data SomeData = A | B | C | D | E deriving (Show, Enum, Bounded)
allData :: SomeData
allData = enumFrom minBound
mapppings = zip (map (toLower.head.show) allData) allData
where the only assumtion I'm making about the future is that it consists of single letters.
However, this is playing and not in fact all that clear.
Upvotes: 3
Reputation: 63379
You can go even more generic:
-- added deriving Bounded
data SomeData = A | B | C | D | E deriving (Show, Enum, Bounded)
fullRange :: (Bounded a, Enum a) => [a]
fullRange = enumFromTo minBound maxBound
and then just call fullRange
(with explicit type annotation if needed: fullRange :: [SomeData]
).
Upvotes: 7
Reputation: 23014
Add Bounded
to your deriving and you can do [minBound ..]
to get a complete list.
Upvotes: 2
Reputation: 152957
If you additionally derive Bounded
, then you can even do this without explicitly knowing what the "smallest" constructor name is:
Prelude> data SomeData = A | B | C | D | E deriving (Show, Enum, Bounded)
Prelude> [minBound :: SomeData ..]
[A,B,C,D,E]
Upvotes: 5
Reputation: 10761
Actually, you could just use a range.
[A .. E]
As described in the invaluable Learn You A Haskell.
Upvotes: 2
Reputation: 969
If you take a look at http://hackage.haskell.org/packages/archive/base/3.0.3.2/doc/html/GHC-Enum.html you can see that the function you need is a part of the Enum
typeclass, if I understand your question correctly.
>enumFrom A
[A, B, C, D, E]
it :: [SomeData]
Upvotes: 2