Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting a list of all possible data type values in Haskell

Not sure if it is an anti-pattern (nor can I think of a good use right now), but it's possible. Use the Enum (allows to generate a list like [someCtor .. someOtherCtor]) and Bounded (for minBound and maxBound) type classes. Luckily, you can derive both:

data Color = Red
           | Yellow
           | Green
           deriving (Enum, Bounded)

allColors = [(minBound :: Color) ..]

If you ever add another color, allColors get updated automatically. One restriction though: Enum requires all contructors to be nullary, i.e. adding Foo Int breaks the whole thing. Luckily, because a list of all possible values for this would be way too large.

Edit: The other answer works as well, maybe better since it doesn't require deriving Bounded and is therefore a bit shorter. I'll still leave mine because I love over-engineered but extremely generic code ;)


Surely delnan's answer is better. Since I do not know how to include a piece of code in a comment, I'll give a generalisation as a separate answer here.

allValues :: (Bounded a, Enum a) => [a]
allValues = [minBound..]

Now, this works for any type with a Bounded and Enum instance! And allColors is just a special case:

allColors :: [Color]
allColors = allValues

In many cases, you won't even need to define allColors separately.


data Color = Red
           | Yellow
           | Green
           deriving Enum

allColors = [Red ..]

Here is an example of using this technique to parse enums with Parsec

data FavoriteColor = Maroon | Black | Green  | Red | 
                     Blue   | Pink  | Yellow | Orange
                             deriving (Show, Read, Enum, Bounded)

And the parsec parser

parseColor :: Parser FavoriteColor           
parseColor = fmap read . foldr1 (<|>) $ map (try . string . show) 
  [ minBound :: FavoriteColor ..] 

of course the try could could be applied by better by pattern matching and a few other things could make it nicer but this is just an example of some usage of the technique.