Question

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 chars 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?

Was it helpful?

Solution

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.

OTHER TIPS

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]).

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]

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]

Actually, you could just use a range.

[A .. E]

As described in the invaluable Learn You A Haskell.

Add Bounded to your deriving and you can do [minBound ..] to get a complete list.

Try this in ghci

> [A ..]
[A,B,C,D,E]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top