Benjamin Kovach
Benjamin Kovach

Reputation: 3260

Is there a simple way to turn a data type deriving Enum into a list?

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?

Upvotes: 3

Views: 394

Answers (7)

AndrewC
AndrewC

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

Petr
Petr

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

augustss
augustss

Reputation: 23014

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

Upvotes: 2

Daniel Wagner
Daniel Wagner

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

Satvik
Satvik

Reputation: 11208

Try this in ghci

> [A ..]
[A,B,C,D,E]

Upvotes: 1

Johanna Larsson
Johanna Larsson

Reputation: 10761

Actually, you could just use a range.

[A .. E]

As described in the invaluable Learn You A Haskell.

Upvotes: 2

identity
identity

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

Related Questions